本文译自 Rapid Event Notification System at Netflix[1]。作者:Ankush Gulati, David Gevorkyan
简介
Netflix有超过2.2亿的活跃会员,时刻在各种界面中都会进行各种操作。为了确保会员体验,Netflix要对这些操作做出实时响应。因为会员操作频繁、支持的设备种类繁多,这对IT团队来说,是一项艰巨的任务。为此,Netflix开发了一个快速事件通知系统(RENO),以支持那些需要以可扩展和可延伸的方式与设备进行服务器启动通信的用例。在这篇文章中,我们将概述Netflix的快速事件通知系统,并分享我们在此过程中获得的一些经验。
动因
随着Netflix会员数量的快速增长和我们系统复杂性的增加,我们的架构已经演变成一个异步的架构,可以同时进行在线和离线计算。在各种平台(iOS、Android、智能电视、Roku、Amazon FireStick、网络浏览器)和各种设备类型(手机、平板电脑、电视、电脑、机顶盒)上提供无缝和一致的Netflix体验,需要的不仅仅是传统的请求-响应模式。随着时间的推移,我们看到越来越多的用例,后端系统需要启动与设备的通信,以通知他们会员驱动的变化或体验的更新,快速和一致。
用户使用场景
- 观看活动:
当一个会员开始观看一个节目时,他们的 "继续观看 "列表应该在他们所有的设备上更新,以反映该观看活动。
- 个性化体验的刷新:
Netflix的推荐引擎不断刷新对每个会员的推荐。更新的推荐需要及时传递到设备上,以获得最佳的会员体验。
- 会员计划的改变:
会员经常改变他们的计划,导致他们的体验发生变化,必须立即反映在他们所有的设备上。
- 会员 "我的名单 "更新:
当会员通过添加或删除标题来更新他们的 "我的名单 "时,这些变化应该反映在他们所有的设备上。
- 会员资料变更:
当会员更新他们的账户设置,如添加/删除/重命名档案或改变他们对内容的首选,这些更新必须反映在他们所有的设备上。
- 系统诊断信号:
在特殊情况下,我们需要向设备上的Netflix应用程序发送诊断信号,以帮助排除问题并启用追踪功能。
设计决定
在设计系统时,我们做出了几个关键决定,这些决定有助于形成RENO的架构:
- 单一事件源
- 事件优先级的确定
- 混合通信模式
- 有针对性的交付
- 管理高RPS
单一事件源
因为我们想要支持的用例来自不同的内部系统和成员行动,所以需要监听来自几个不同微服务的事件。在Netflix,我们近乎实时的事件流是由一个叫做Manhattan的内部分布式计算框架管理的。我们利用Manhattan的事件管理框架来创建一个间接层来作为RENO的单一事件来源。
事件优先级的确定
考虑到用例在来源和重要性方面都很广泛,我们在事件处理中进行了细分。例如,一个由成员触发的事件,如 "配置文件的成熟度变化",应该比 "系统诊断信号 "有更高的优先级。因此,我们为每个用例分配了一个优先级,并通过路由到特定优先级的队列和相应的事件处理集群来分流事件流量。这种分离使我们能够针对不同的事件优先级和流量模式独立调整系统配置和扩展策略。
混合通信模式
正如本文前面提到的,像RENO这样的服务的一个关键挑战是支持多种平台。虽然移动设备几乎总是连接到互联网并可以到达,但智能电视只有在使用时才会在线。这种网络连接的异质性使得选择一个单一的交付模式很困难。例如,完全依靠设备经常给家里打电话更新的Pull模式会导致移动应用程序的聊天。这反过来又会触发iOS和Android平台强制执行的每个应用的通信限制(我们还需要考虑到低带宽连接)。另一方面,只使用推送机制会导致智能电视错过通知,而它们在一天中的大部分时间都是关闭电源的。因此,我们选择了一个混合的 "推 "和 "拉 "的通信模型,其中服务器试图使用 "推 "通知立即向所有设备发送通知,而设备则在应用生命周期的不同阶段打电话回家。使用 "推 "和 "拉 "的组合交付模式也支持仅限于单一通信模式的设备。这包括不支持推送通知的旧有设备。
有针对性的交付
考虑到用例在来源和目标设备类型方面的广泛性,我们建立了对设备特定通知交付的支持。这种能力允许根据用例通知特定的设备类别。当一个可操作的事件到来时,RENO应用用例特定的业务逻辑,收集有资格接收该通知的设备列表并尝试交付。这有助于大大限制流出的流量足迹。
管理高RPS
拥有超过2.2亿的会员,我们意识到,像RENO这样的服务需要在观看会话期间处理每个会员的许多事件。在高峰期,RENO每秒钟提供约15万个事件。在一天的特定时间内,如此高的RPS会造成雷同的羊群问题,给内部和外部的下游服务带来压力。因此,我们实施了一些优化措施:
- 事件Age
许多需要通知设备的事件是时间敏感的,除非几乎立即发送,否则它们没有或几乎没有价值。为了避免处理旧的事件,一个陈旧性过滤器被应用作为门控检查。如果一个事件的Age超过一个可配置的阈值,它就不会被处理。这个过滤器在处理阶段的早期剔除了对设备没有价值的事件,并保护队列不被可能已经被备份的陈旧的上游事件淹没。
- 在线设备
为了减少持续的流量占用,通过利用Zuul保持最新的现有注册表,只向当前在线的设备发送通知。
- 扩展策略
为了解决羊群问题,并将延迟保持在可接受的阈值之下,集群的扩展策略被配置为“更积极的扩展策略”。这种方法使计算能力在队列增长时能够迅速赶上。
- 事件重复数据删除
iOS和安卓平台都积极限制后台应用程序产生的活动水平,因此在RENO中对传入的事件进行重复计算的原因。在高RPS的情况下,可能会出现重复的事件,在不会对设备造成任何损失的情况下,它们被合并在一起。
- 批量发送
多个下游服务被用来向不同的设备平台发送推送通知,包括像苹果设备的Apple Push Notification Service(APNS)和谷歌的安卓的Firebase Cloud Messaging(FCM)等外部服务。为了防止下游服务导致整个通知服务瘫痪,事件的发送在不同的平台上是并行的,使其成为每个平台的最佳努力。如果一个下游服务或平台未能交付通知,其他设备不会被阻止接收推送通知。
架构图
如上图所示,RENO服务可细分为以下部分。
事件触发器
需要在会员的设备上刷新体验的会员行动和系统驱动的更新。
事件管理引擎
Netflix的近实时事件流管理框架被称为Manhattan,可以被配置为监听特定的事件并将事件转发到不同的队列。
基于事件优先级的队列
AWS SQS队列由基于优先级的事件转发规则填充,在Manhattan中设置,允许基于优先级的流量分片。
基于事件优先级的集群
AWS实例集群,以相同的优先级订阅相应的队列。它们处理所有到达这些队列的事件然后生成可操作的通知。
出站消息系统
Netflix消息系统来向用户移动设备发送RENO制作的通知。这篇博文中描述了这个消息系统。对于网络、电视和其他流媒体设备的通知,我们使用一个自制的推送通知解决方案,称为Zuul Push,提供与在线设备的 "永远在线 "的持久连接。
持久性存储
Cassandra数据库存储RENO为每个设备发出的所有通知,它让这些设备能够按照自己的节奏轮询它们的信息。
可观察性
为了提供一个清晰的系统健康视图,在Netflix非常注重系统中监控的建立。对于像RENO这样的高RPS服务,它依赖于几个上游系统作为其流量来源,并同时为不同的内部和外部下游系统产生大量的流量,因此有一个强大的指标、警报和日志的组合是很重要的。在警报方面,除了标准的系统健康指标,如CPU、内存和性能,我们还增加了一些 "服务边缘 "指标和日志记录,以捕捉来自上游或下游系统的任何异常情况。此外,除了实时警报,我们还增加了重要指标的趋势分析,以帮助捕捉长期的退化。我们用一个名为Mantis的实时流处理应用程序来检测RENO。它使我们能够在设备特定的颗粒度上通过电线实时跟踪事件,从而使调试更容易。最后,我们发现拥有特定平台的警报(针对iOS、Android等)对更快地找到问题的根源很有帮助。
获益
- 可以轻松支持新的使用案例
- 以更高的吞吐量进行横向扩展
当我们开始建立RENO时,目标仅限于产品的 "个性化体验更新 "用例。随着RENO设计的发展,对新用例的支持成为可能,RENO很快被定位为Netflix所有产品领域的集中式快速通知服务。
我们在早期做出的设计决定得到了回报,例如使增加新的用例成为一个 "即插即用 "的解决方案,并在所有平台上提供一个混合交付模式。我们能够以很快的速度加入更多的产品用例,从而疏通了大量的创新。
构建这个平台的一个重要经验是确保RENO可以横向扩展,因为随着时间的推移需要更多类型的事件和更高的吞吐量。这种能力主要是通过允许基于事件类型或优先级的分片来实现的,同时使用异步事件驱动的处理模型,可以通过简单地增加事件处理的机器来进行扩展。
展望未来
随着Netflix的会员数量持续快速增长, RENO可以帮助我们的会员获得最佳和最新的Netflix体验。随着我们对会员体验的不断创新,我们正在不断地发展我们的通知组合。在架构上,我们正在评估建立更多功能的机会,如保证信息传递和信息批处理,这可以开辟更多的使用案例,并帮助减少RENO的通信足迹。
引用链接
[1]
原文链接: https://netflixtechblog.com/rapid-event-notification-system-at-netflix-6deb1d2b57d1