Netflix的微服务架构为其提供全球视频流服务,本篇文章将对此架构进行全面的系统设计分析。
1. 简介
Netflix多年来一直是全球最出色的在线订阅制的视频流服务之一,其占世界互联网带宽容量的15%以上。2019年,Netflix已经获得了超过1.67亿的订阅用户,每个季度新增用户超过500万,服务涵覆盖全球200多个国家或地区。更具体点说,Netflix的用户每天要花费超过1.65亿小时观看4000多部电影和47000多集电视剧。这些令人印象深刻的数据从工程设计的角度来看,Netflix的技术团队已经设计了一个惊人的视频流系统,其具有高可用性和可扩展性,以服务其全球客户。
然而,这可是其技术团队花费了超过8年的时间才将他们的IT系统升级到现在的规模。事实上,Netflix的基础架构转型始于2008年8月,触发点是当时数据中心的服务中断导致整个DVD租赁服务关闭了三天。Netflix意识到它需要一个没有单点故障的更可靠的基础架构。为此,它做出了两个重要的决定:将IT基础架构从其数据中心迁移到公有云,并使用微服务架构的小型可管理软件组件替换其单体应用程序。这两个决定直接塑造了Netflix今天的成功。
Netflix选择AWS Cloud来迁移其IT基础架构,因为AWS可以在全球范围提供高度可靠的数据库、大规模云存储和多个数据中心。通过使用AWS建立和维护的云基础架构,Netflix不再去做那些建设数据中心时需要去做的重复的繁重的工作,而是更加专注于他们的核心业务——提供高质量视频流以及提高用户体验。尽管它必须重新构建整个技术,使其能够在AWS云上平稳运行,但Netflix的可扩展性和服务可用性得到了相当显著地改善。
Netflix也是微服务架构背后的首要驱动者之一。微服务通过引入关注点分离来解决单体软件设计的问题,其中通过模块化和数据封装将大程序分解为更小的组件。微服务还可以通过水平扩展和工作负载分区帮助提高可扩展性。通过采用微服务,Netflix的工程师可以很容易地改变任何能加快部署速度的服务。更重要的是,他们可以跟踪每个服务的性能,并快速地将某个问题与其他正在运行的服务隔离开。
本研究中,我比较有兴趣去了解Netflix的云架构及其在不同工作负载和网络限制下的性能。具体来说,我想从可用性、延迟、可扩展性和对网络故障或系统中断的弹性方面分析系统设计。本研究如下:第二部分将描述从各种在线资源中学习到的可能的Netflix系统架构。然后在第3节中,将讨论更详细的系统组件。在第4、5、6、7节中,我将针对上述设计目标对系统进行分析。最后,我将总结从这一分析中得到的教训以及可能后续需要采取的改进。
2. 架构
Netflix运营在基于亚马逊云计算服务(AWS)和其自研的内容交付网络Open Connect上。这两个系统必须无缝合作,才能在全球提供高质量的视频流服务。从软件架构的角度来看,Netflix包括三个主要部分:客户端、后端和内容分发网络(CDN)。
客户端指的是笔记本或台式机上支持的任何浏览器,或智能手机或智能电视上的Netflix应用程序。Netflix开发了自己的iOS和Android应用程序,为每一个客户端和设备提供最佳的观看体验。通过SDK控制其应用程序和其他设备,在某些情况下Netflix可以透明地调整其流服务,如网速慢或服务器过载。
后端包括完全在AWS云上运行的服务、数据库和存储。后台基本上除了不涉及流视频,它处理一切事务。后台部分组件及其相应的AWS服务如下:
可伸缩的计算实例(AWS EC2)
可扩展存储(AWS S3)
业务逻辑微服务(Netflix特有的框架)
可扩展的分布式数据库(AWS DynamoDB, Cassandra)
大数据处理和分析工作(AWS EMR、Hadoop、Spark、Flink、Kafka和Netflix的其他专有工具)
视频处理和代码转换(Netflix特有的工具)
Open Connect CDN是一个名为Open Connect Appliance (OCA)的服务器网络,为存储和播放大型视频进行了优化。这些OCA服务器被放置在世界各地的互联网服务提供商(ISP)和互联网交换中心(IXP)网络中。OCA负责将视频直接传输给客户。
在接下来的章节中,我将描述由以上三部分组成的Netflix云架构。在第2.1节中,一个整体的架构是,在用户点击他或她的应用程序上的播放按钮后,能够通过流播放视频,也被称为回放架构(Playback Architecture)。然后在第2.2节中,将描述一个更详细的后端微服务架构,以演示Netflix如何在全球范围内处理可用性和可扩展性。
2.1 Playback架构
当用户在他们的应用程序或设备上点击播放按钮时,客户端将与AWS上的后端和Netflix CDN上的OCA进行对话,以播放视频。下图展示了Playback过程的工作原理:
图1 流视频Playback架构
OCA不断发送有关其工作负载状态、可路由性和可用视频的健康报告,此报告发送给位于AWS EC2的缓存控制中心,以便Playback应用程序将最新且健康的OCA更新到客户端。
播放请求从客户端设备发送到运行在AWS EC2上的Netflix播放应用程序服务,以获取流视频的URL。
播放应用程序服务必须确定播放请求将是有效的,才能查看特定的视频。这些验证将检查订阅者的订阅计划、不同国家的视频许可等。
Playback应用服务与在AWS EC2中运行的引导服务对话,以获得所请求视频的最合适的OCA服务器的列表。引导服务使用客户端IP地址和ISP信息来识别一组最适合该客户端的OCA。
从Playback应用服务返回的10个不同的OCA服务器列表中,客户端测试到这些OCA的网络连接质量,并选择最快、最可靠的OCA来请求流传输。
所选的OCA服务器接受来自客户端的请求并开始流传输视频。
在上图中,Playback应用服务、引导服务和缓存控制服务完全在基于微服务架构的AWS云上运行。在下一节中,我将介绍Netflix后端微服务架构,该架构提高了当前服务的可用性和可扩展性。
2.2 后端架构
如前所述,后端几乎处理所有内容,从注册、登录、计费到更复杂的处理任务,如视频转码和个性化推荐等。为了支持在同一底层基础架构上运行的轻量级和重型工作负载,Netflix为其基于云的系统选择了微服务架构。图2展示了Netflix可能使用的微服务架构,这是我从几个在线资源分析后总结的:
图2 基于多种来源的后端架构参考
客户端向AWS上运行的后端发送播放请求。该请求由AWS负载均衡(ELB)处理。
AWS ELB将该请求转发给运行在AWS EC2实例上的API网关服务。该组件名为Zuul,是由Netflix团队构建的,提供动态路由、流量监控和安全性,以及对云部署的边缘故障提供恢复能力。该请求将应用于一些与业务逻辑相对应的预定义过滤器上,然后转发给应用程序(Application)API做进一步处理。
Application API组件是Netflix运营背后的核心业务逻辑。有几种类型的API对应于不同的用户活动,如注册API和用于检索视频推荐的推荐API。在这个场景中,来自API网关服务的转发请求由Play API处理。
播放(Play) API将调用一个微服务或一系列微服务来满足请求。图1中的Playback应用程序服务、指导服务和缓存控制服务可以在该图中视为微服务。
微服务大多是无状态的小程序,也可以相互调用。为了控制其级联故障并启用弹性,每个微服务都通过Hystrix与调用方进程隔离。其运行后的结果可以缓存在基于内存的缓存中,以便更快速的访问那些关键的低延迟请求。
整个流程里,微服务可以保存数据或从数据存储获取数据。
微服务可以将用于跟踪用户活动的事件或其他数据发送到流处理管道(Stream Processing Pipeline),以便实时处理个性化推荐或批处理业务智能任务。
来自流处理管道的数据可以持久化到其他数据存储,如AWS S3、Hadoop HDFS、Cassandra等。
上述架构可以帮助我们概括了解系统的各个部分如何组织和协同工作以流传输视频。然而,要分析架构的可用性和可扩展性,我们需要深入研究每个重要的组件,以了解它在不同工作负载下的执行情况。这将在下一节中具体讨论。
3. 组件
在本节中,我将研究第2节中定义的组件,以分析其可用性和可扩展性。在描述每个组件时,我还会说明它是如何满足这些设计目标。在以后的章节中,将会对整个系统进行更深入的设计分析。
3.1 客户端
Netflix的技术团队投入了大量精力来开发运行在笔记本、台式机或移动设备上的更快、更智能的客户端应用程序。甚至在一些智能电视上,Netflix并没有建立一个专门的客户端,Netflix仍然通过自己的SDK来控制它的性能。事实上,任何设备环境都需要安装Netflix就绪设备平台(Netflix Ready Device Platform NRDP),以实现最佳的Netflix观看体验。一个典型的客户端结构组件如图3所示。
图3 客户端应用程序组件
客户端应用程序为内容发现和内容播放分离成两种类型的后端连接。客户端使用NTBA协议处理Playback请求,以确保其OCA服务器位置的安全性,并消除新连接的SSL/TLS握手引起的延迟。
在流传输视频时,如果网络连接过载或出现错误,客户端应用程序会智能降低视频质量或切换到不同的OCA服务器。即使连接的OCA过载或失败,客户端应用程序也可以轻松切换到另一个OCA服务器,以获得更好的观看体验。之所以这些能够实现,是因为客户端上的Netflix平台SDK一直跟踪从Playback Apps服务中检索到的最新的健康OCA列表。
3.2 后端
3.2.1 API网关服务
API网关服务组件与AWS负载均衡器通信,以解决来自客户端的所有请求。该组件可以跨不同区域部署到多个AWS EC2实例,以提高Netflix服务的可用性。图4中的图展示了一个开源的Zuul,这是一个由Netflix团队创建的API网关的实现。
图4 Zuul网关服务组件
入站过滤器(Inbound Filter)可用于身份验证、路由和装饰请求。
端点过滤器(Endpoint Filter)可用于返回静态资源或将请求路由到适当的源或应用程序API进行进一步处理。
出站过滤器(Outbound Filter)可用于跟踪指标、装饰对用户的响应或添加自定义头。
Zuul能够通过与服务发现组件Eureka集成来发现新的应用程序API。
Zuul广泛用于针对各种需求的流量路由,如新应用程序API的加载、负载测试、在大工作负载下路由到不同的服务端点。
3.2.2 应用程序API
应用程序API充当Netflix微服务的编配层。API提供了一种逻辑,按照所需的顺序组合对底层微服务的调用,以及来自其他数据存储的额外数据,以构造适当的响应。Netflix团队已经花费了大量的时间来设计应用程序API组件,因为它与Netflix的核心业务功能相对应。在高请求容量下具有高可用性和可扩展性。目前,应用程序API被定义为三类:注册Signup API(用于非会员请求,如注册、计费、免费试用等)、搜索发现Discovery API (用于推荐请求)、和播放Play API(用于流播放和查看许可请求)。图5提供了应用程序API的详细结构组件图。
图5 播放和发现应用程序API的分离
在Play API的最新更新中,Play API和微服务之间的网络协议是gRPC/HTTP2,它“允许通过协议缓冲区定义RPC方法和实体,并以各种语言自动生成客户端库或SDK”。这个改变允许应用程序API通过双向通信与自动生成的客户端适当地集成,并“尽可能减少跨服务边界的代码重用”。
Application API还提供了基于Hystrix命令的通用弹性机制,以保护其底层微服务。
由于Application API必须处理大量的请求并构造适当的响应,因此它的内部处理需要高度并行的方式运行。Netflix团队发现同步执行和异步I/O相结合才是正确的方式。
图6 Application API的同步执行和异步I/O
来自API网关服务的每个请求将被放置到应用程序API的网络事件循环(Network Event Loop)中进行处理
每个请求都将被一个专门的线程处理程序阻止,该程序将Hystrix命令(如getCustomerInfo、getDeviceInfo等)放入传出事件循环(Outgoing Event Loop)中。每个客户端都设置这个传出事件循环,并非以阻塞I/O运行。一旦调用微服务完成或超时,上述专用线程将构造对应的响应。
3.2.3 微服务
根据Martin Fowler的定义,“微服务是一套小型服务,每个服务都在自己的进程中运行,并与轻量机制进行通信……”。相对于其他程序,这些小程序可以独立部署或升级,并拥有自己的封装数据。
图7展示了Netflix的微服务组件的实现。
图7 微服务的结构组件
微服务可以独立工作,也可以通过REST或gRPC调用其他微服务。
微服务的实现可以类似于图6中描述的Application API,在图6中,请求将被放入网络事件循环中,来自其他被调用的微服务的结果将以异步非阻塞I/O的方式放入结果队列。
每个微服务可以有自己的数据存储和一些存放近期结果的内存缓存存储。EVCache是Netflix微服务缓存的主要选择。
3.2.4 数据存储
Netflix在将基础架构迁移到AWS云上时,使用了不同的数据存储(图8),包括SQL和NoSQL,来完成不同的目的。
图8 在AWS上部署Netflix数据存储
MySQL数据库用于电影名管理和交易/下单目的。
Hadoop用于基于用户日志的大数据处理。
Elasticsearch为Netflix提供了标题搜索能力。
Cassandra是一个基于分布式的NoSQL数据存储,用于处理大量的读请求,没有单点故障。为了优化大规模写请求的延迟,Netflix使用了Cassandra,因为它具有最终一致性的能力。
3.2.5 流程处理管线(Stream Processing Pipeline)
流处理数据管道已经成为Netflix的业务分析和个性化推荐任务的数据支柱。它负责生成、收集、处理、和汇总所有微服务事件,并几乎实时地移动到其他数据处理器上。图9显示了该平台的各个部分。
图9 Netflix的Keystone流处理平台
流处理平台每天处理数万亿级的事件和PB级的数据。它还会随着用户数量的增加而自动扩展。
路由器模块支持路由到不同的数据接收器(sink)或应用程序,同时Kafka负责路由消息以及对下游系统的缓冲。
流处理即服务(Stream Processing as a Service SPaaS)允许数据工程师构建和监控他们自建的托管流处理应用程序,而平台将负责可扩展性和日常运维。
3.3 Open Connect
Open Connect是一个全球内容交付网络(Content Delivery Network CDN),负责存储和传送Netflix的电视节目和电影到世界各地的用户。Netflix通过将人们想要观看的内容尽可能的靠近他们的物理位置,构建建立和运营了这一个高效的Open Connect网络。为了将观看Netflix视频的流量定位到客户的网络,Netflix已经与全球互联网服务提供商(ISP)和互联网交换点(IX或IXP)合作,在他们的网络中部署名为Open Connect Appliances(OCA)的专用设备。
图10 将OCA部署到IX或ISP站点
OCA是经过优化的服务器,用于存储大型视频文件并将其从IX或ISP站点直接传输到订阅者的家中。这些服务器定期向AWS的Open Connect 控制平面(Control Plane)报告他们从IXP/ISP网络学到的健康指标最佳路线,以及他们在SSD磁盘上存储什么视频。作为回报,控制平面服务将获取这些数据,根据文件可用性、服务器运行状况和与客户端网络的接近程度,自动将客户端设备定向到最佳的OCA。
控制平面服务还控制在OCA上添加新文件或更新文件的填充(filling)行为。填充行为如图11所示。
当新的视频文件成功转码并存储在AWS S3上时,AWS上的控制平面服务将把这些文件传输到IXP站点上的OCA服务器。这些OCA服务器将应用缓存填充(Cache Fill)来将这些文件传输到其子网下ISP站点的OCA服务器上。
当OCA服务器成功存储视频文件时,如果需要,它将能够启动对等填充(Peer Fill),将这些文件复制到同一站点内的其他OCA服务器上。
在两个可以看到彼此IP地址的不同站点之间,OCA可以应用层填充(Tier Fill)流程,而不是常规的缓存填充。
图11 OCA中的填充模式
4. 设计目标
在前面的小节中,我已经详细描述了Netfilx视频流业务的云架构及其组件。在这一节和后面的几节中,我想更深入地分析这个设计架构。首先列出最重要的设计目标,如下:
确保流服务在全球范围内的高可用性。
弹性处理网络故障和系统中断。
在各种网络条件下,最小化每个设备的流延迟。
支持高请求量的可扩展性。
在下面的小节中,我将分析流服务的可用性及其相应的最佳延迟。第6节更深入地分析了诸如混沌工程(Chaos Engineering)之类的弹性机制,而第7节则介绍了流服务的可扩展性。
4.1 高可用性
根据定义,系统的可用性是根据在一段时间内的请求被满足的次数来度量的,而不需要保证它包含信息的最新版本。在我们的系统设计中,流服务的可用性取决于后端服务和服务器二者的可用性。
后端服务的目标是通过缓存或执行某些微服务获得与最接近指定客户端最健康的OCA的列表。因此,它的可用性取决于涉及Playback请求的各种组件:负载均衡器(AWS ELB)、代理服务器(API网关服务)、播放API、微服务执行、缓存存储(EVCache)和数据存储(Cassandra):
负载均衡器可以通过将流量路由到不同的代理服务器来提高可用性,以防止工作负载过载。
播放API通过Hystrix命令使用超时(timeout)来控制微服务的执行,从而防止级联故障影响其他服务。
微服务可以使用缓存中的数据来响应播放API,以防对外部服务或数据存储的调用花费比预期更多的时间。
复制缓存以便用户可以更快地访问。
当从后端接收到OCA服务器列表时,客户端将网络探测到这些OCA并选择要连接的最佳OCA。如果该OCA在流过程中过载或失败,则客户端切换到另一个好OCA,否则平台SDK将请求其他OCA。因此,它的可用性与ISPs或IXPs中所有OCA的可用性高度相关。
Netflix流服务的高可用性是以复杂的多区域AWS运维和服务以及OCA服务器的冗余为代价的。
4.2 低延迟
流服务的延迟主要取决于Play API解析健康OCA列表的速度,以及客户端与所选OCA服务器的连接情况。
正如我在Application API组件一节中所描述的,Play API不会永远等待微服务的执行,因为它使用Hystrix命令来获取到结果之前要等待的时间,一旦超时立即从缓存获取非最新的数据。这样做可以把延迟控制在可接受的范围,并停止级联故障影响更多服务。
如果当前选定的OCA服务器出现网络故障或该服务器过载,客户端将立即切换到其他附近且网络可靠的OCA服务器。当发现网络连接不好,还可以降低视频质量以匹配网络质量。
5. 权衡(Trade-offs)
在上面描述的系统设计中,有两个突出的权衡点已经被仔细地实现了:
低延迟超过一致性
高可用性高于一致性
在后端服务的架构设计中就已经选择了用一致性来换取低延迟。Play API可以从EVCache存储或最终一致的数据存储如(Cassandra)中获取过时的数据。
类似地,所谓用一致性换取高可用性的权衡就是,系统希望以可接受的延迟发起响应,而不会对像Cassandra这样的数据存储中的最新数据执行微服务。
在可扩展性和性能之间还存在不太相关的权衡。在这种权衡下,通过增加实例数量来处理更多的负载,从而提高可扩展性,这可能会导致系统在预期性能提高的情况下运行。这可能是架构设计的问题,在这些架构中,负载在可用的工作节点之间没有很好地平衡。不过,Netflix已经解决了与AWS自动扩展的权衡问题。我们将在第7节中更详细地讨论这个方案。
6. 弹性(Resilience)
从迁移到AWS云服务的第一天起,设计一个能够从故障或停机中自我恢复的云系统就一直是Netflix的长期目标。本系统的一些常见故障如下:
解析服务依赖项失败。
执行微服务的失败将导致对其他服务的级联失败。
由于过载而无法连接到某个API。
连接到实例或服务器(如OCA)的失败。
为了检测和解决这些故障,API网关服务Zuul具有内置的特性,例如自适应重试,从而限制对Application API的并发调用。反过来,Application API使用Hystrix命令暂停对微服务的调用,停止级联故障并将故障点与其他故障点隔离开来。
Netflix的技术团队也以其在混乱工程的实践而闻名。其思想是将伪随机错误注入生产环境,并构建解决方案来自动检测、隔离,并从此类故障中恢复。错误可能是在执行微服务、杀死服务、停止服务器或实例、甚至导致整个区域的基础架构瘫痪的响应中增加延迟。通过有目的地将真实的生产故障引入到监控的环境中,并使用工具来检测和解决此类故障,Netflix可以在造成更大的问题之前提早发现这些缺陷。
7. 可扩展性(Scalability)
在本节中,我将分析Netflix流服务的可扩展性,包括水平扩展、并行执行和数据库分区。其他部分如缓存和负载均衡也有助于提高可扩展性,这在第4节中已经提到过。
首先,Netflix的EC2实例的水平扩展是由AWS自动扩展服务(Auto Scaling Service)提供的。当请求量增加并关闭未使用的实例,AWS服务将自动生成更多的弹性实例。更具体地说,在数千个这样的实例之上,Netflix构建了一个开源容器管理平台Titus,每周可运行大约300万个容器。同样,我们的架构图2中的任何组件都可以部署在容器中。此外,Titus允许容器在世界各地不同大洲的多个区域运行。
其次,第3.2.2节中,通过允许在网络事件循环和异步传出事件循环上并行执行任务,Application API或微服务也提高了可扩展性。
最后,像Cassandra这样的宽列存储和像ElasticSearch这样的键值存储也提供了高可用性和高可扩展性,同时没有单点故障。
8. 结论
此篇研究描述了Netflix流服务的整个云架构。它还分析了在可用性、延迟、可扩展性和对网络故障或系统中断的弹性方面的不同设计目标。简而言之,Netflix的云架构通过被自己的生产系统证明,它可以运行在数千台虚拟服务器上为数百万用户提供服务,并通过与AWS云服务的集成和全球范围的网络故障和系统中断的弹性能力,展示了具有最佳延迟的高可用性、强大的可扩展性。本文提到的大多数架构和组件都是通过互联网上可信的资源总结出来的。尽管网上没有太多描述微服务的内部实现以及监控其性能的工具和系统的直接资源,但本研究可以作为如何构建典型生产系统的参考实现。
原文链接:https://medium.com/swlh/a-design-analysis-of-cloud-based-microservices-architecture-at-netflix-98836b2da45f
Kubernetes实战培训
Kubernetes实战培训将于2020年12月25日在深圳开课,3天时间带你系统掌握Kubernetes,学习效果不好可以继续学习。本次培训包括:云原生介绍、微服务;Docker基础、Docker工作原理、镜像、网络、存储、数据卷、安全;Kubernetes架构、核心组件、常用对象、网络、存储、认证、服务发现、调度和服务质量保证、日志、监控、告警、Helm、实践案例等,点击下方图片或者阅读原文链接查看详情。