Categories
程式開發

全面解析Netflix的微服务架构设计


全面解析Netflix的微服务架构设计 1

本文最初发布于Medium博客,经原作者授权由InfoQ中文站翻译并分享。

一、简介

多年来,Netflix一直是全球最出色的在线订阅制视频流媒体服务,其流量占全球互联网带宽容量的15%以上。截至2019年,Netflix已拥有1.67亿订阅用户,每个季度新增500万订户,服务覆盖全球200多个国家/地区。Netflix用户每天在4000多部电影和47000集电视剧上花费超过1.65亿小时的时间。从工程角度看,这些令人印象深刻的统计数据向我们展示了Netflix的技术团队设计出了多么优秀的视频流系统;这套系统具有很高的可用性和可扩展性,能为全球客户提供服务。

但是,该公司的技术团队花了超过8年时间才打造出今天这样强大的IT系统。实际上,Netflix的基础架构转型始于2008年8月,当时他们的数据中心遇到了服务中断的故障,导致整个DVD租赁服务关闭三天。Netflix意识到,它需要一个没有单点故障的更可靠的基础架构。因此它做出两个重要决定:将IT基础架构从自己的数据中心迁移到公共云上,并通过微服务架构,用较小的易管理软件组件替换单体程序。这两个决定为今天Netflix的成功打下了坚实基础。

Netflix之所以选择AWS云来迁移其IT基础架构,是因为AWS可以在全球范围内提供高度可靠的数据库、大规模云存储和众多数据中心。Netflix利用了由AWS构建和维护的云基础架构,从而免去自建数据中心的繁重重复劳动,并将更多精力放在提供高质量视频流体验的核心业务上。尽管Netflix必须重建整个技术体系,以使其能在AWS云上平稳运行,但作为回报,系统的可扩展性和服务可用性得到显著提高。

Netflix还是微服务架构背后的首批主要推动者之一。微服务鼓励关注点分离来解决单体软件设计存在的问题。在这种架构中,大型程序通过模块化和独立的数据封装被分解为许多较小的软件组件。微服务还通过水平扩展和工作负载分区来提升可扩展性。采用微服务后,Netflix工程师可以轻松更改任何服务,从而加快部署速度。更重要的是,他们能跟踪每个服务的性能水平,并在其出现问题时与其他正在运行的服务快速隔离开来。

二、架构

Netflix基于亚马逊云计算服务(AWS),及公司内部的内容交付网络Open Connect运营。两套系统必须无缝协作才能在全球范围内提供高质量的视频流服务。从软件架构的角度来看,Netflix包括三大部分:客户端、后端和内容交付网络(CDN)。

客户端是用户笔记本电脑或台式机上所有受支持的浏览器,或者智能手机/智能电视上的Netflix应用。Netflix开发了自己的iOS和Android应用,试图为每个客户端和每台设备都能提供最佳的观看体验。Netflix可以通过其SDK控制自己的应用和其他设备,从而在某些场景下(例如网络速度缓慢或服务器超载)透明地调整流服务。

后端包括完全在AWS云上运行的服务、数据库和存储。后端基本上可以处理不涉及流视频的所有内容。后端的某些组件及其对应的AWS服务列举如下:

  • 可扩展计算实例(AWS EC2)
  • 可扩展存储(AWS S3)
  • 业务逻辑微服务(Netflix专用框架)
  • 可扩展的分布式数据库(AWS DynamoDB、Cassandra)
  • 大数据处理和分析作业(AWS EMR、Hadoop、Spark、Flink、Kafka和一些Netflix专用工具)
  • 视频处理和转码(Netflix专用工具)

Open Connect CDN是称为Open Connect Appliances(OCAs)的服务器网络,已针对存储和流传输大尺寸视频进行了优化。这些OCA服务器放置在世界各地的互联网服务提供商(ISP)和互联网交换位置(IXP)网络内。OCA负责将视频直接流传输到客户端。

2.1 Playback架构

当订阅者单击应用或设备上的播放按钮时,客户端将与AWS上的后端和Netflix CDN上的OCA对话以流传输视频。下图说明了playback流程的工作机制:

全面解析Netflix的微服务架构设计 2

用于流视频的playback架构

  1. OCA不断将关于其负载状态、可路由性和可用视频的运行状况报告发送到在AWS EC2中运行的缓存控制(Cache Control)服务上,以便Playback应用向客户端更新最新的健康OCA。
  2. 播放(Play)请求从客户端设备发送到在AWS EC2上运行的Netflix播放应用服务,以获取流视频的URL。
  3. Playback应用服务必须确定播放请求是有效的,才能观看特定视频。这里的验证流程将检查用户的订阅计划,以及在不同国家/地区的视频许可等。
  4. Playback应用服务会与同在AWS EC2中运行的引导(Steering) 服务对话,以获取所请求视频的合适的OCA服务器列表。引导服务使用客户端的IP地址和ISP信息来确定一组最适合该客户端的OCA。
  5. 客户端从Playback应用服务返回的10个OCA服务器的列表中测试这些OCA的网络连接质量,并选择最快、最可靠的OCA来请求视频文件,进行流传输。
  6. 选定的OCA服务器接受来自客户端的请求并开始流传输视频。

在上图中,Playback应用服务、引导服务和缓存控制服务完全在基于微服务架构的AWS云中运行。在下一节中我将介绍Netflix后端微服务架构,该架构可提高当前服务的可用性和可扩展性。

2.2 后端架构

如前所述,后端要处理几乎所有内容,从注册、登录、计费到更复杂的处理任务,如视频转码和个性化推荐等无所不包。为同时支持在同一底层基础架构上运行的轻量与重量级负载,Netflix为其基于云的系统选择了微服务架构。图2展示了Netflix可能使用的微服务架构,我从一些在线资源中总结出了这些架构形态:

全面解析Netflix的微服务架构设计 3

基于多种来源分析得出的后端架构参考

  1. 客户端向在AWS上运行的后端发送一个播放请求。该请求由AWS负载均衡器(ELB)处理。
  2. AWS ELB会将请求转发到在AWS EC2实例上运行的API网关服务上。名为Zuul的组件是由Netflix团队构建的,提供动态路由、流量监控和安全性,以及对云部署边缘故障的恢复能力。该请求将应用在与业务逻辑对应的一些预定义过滤器上,然后转发到应用程序(Application)API做进一步处理。
  3. 应用程序API组件是Netflix运营背后的核心业务逻辑。有几种类型的API对应不同的用户活动,如注册API和用于检索视频推荐的推荐API等。在这里,来自API网关服务的转发请求由播放API处理。
  4. 播放API将调用一个或一系列微服务来满足请求。图1中的播放应用服务、引导服务和缓存控制服务可以视为微服务。
  5. 微服务主要是无状态的小型程序,并且也可以相互调用。为了控制其级联故障并获得弹性,Hystrix将每个微服务与调用者进程隔离开来。其运行结果可以缓存在基于内存的缓存中,以更快地访问那些关键的低延迟请求。
  6. 微服务能在流程中保存到数据存储或从数据存储中获取数据。
  7. 微服务可以将用于跟踪用户活动或其他数据的事件发送到流处理管道(Stream Processing Pipeline),以实时处理个性化推荐任务,或批处理业务智能任务。
  8. 来自流处理管道的数据能持久存储到其他数据存储中,如AWS S3、Hadoop HDFS和Cassandra等。

上述架构可以帮助我们概括了解系统的各个部分如何组织和协同工作以流传输视频。但要分析这一架构的可用性和可扩展性,我们需要深入研究每个重要组件,以了解其在不同负载下的性能表现。下一节将具体介绍这部分内容。

3.组件

本节会深入研究第2节中定义的组件,以分析其可用性和可扩展性。在介绍每个组件时,我还将说明它们是如何满足这些设计目标的。在后面的章节中将对整个系统进行更深入的设计分析。

3.1 客户端

Netflix技术团队投入了大量精力来开发能在笔记本、台式机或移动设备上运行得更快、更智能的客户端应用。即使在某些没有专用Netflix客户端的智能电视上,Netflix仍然可以通过自己提供的SDK来控制设备的性能表现。实际上,任何设备环境都需要安装Netflix Ready Device Platform(NRDP),以实现最佳的观看体验。图3展示了一个典型的客户端结构组件。

全面解析Netflix的微服务架构设计 4

客户端应用组件

  • 客户端应用(Client App)会将自己与后端的连接分为2种类型,分别用于内容发现(Content discovery)和内容播放。客户端对播放请求使用NTBA协议,以确保其OCA服务器位置具有更高的安全性,并消除了新连接的SSL/TLS握手引起的延迟。
  • 在流传输视频时,如果网络连接过载或出现错误,客户端应用会智能地降低视频质量或切换到其他OCA服务器上。即使连接的OCA过载或出现故障,客户端应用也可以轻松切换为其他OCA服务器,以获得更好的观看体验。之所以客户端能实现所有这些目标,是因为其上的Netflix Platform SDK一直在跟踪从播放应用服务中检索到的最新健康OCA列表。

3.2 后端

3.2.1 API网关服务

API网关服务(API Gateway Service)组件与AWS负载均衡器(Load Balancer)通信以解析来自客户端的所有请求。该组件可以部署到位于不同区域的多个AWS EC2实例上,以提高Netflix服务的可用性。图4展示了开源的Zuul,这是Netflix团队创建的API网关的实现。

全面解析Netflix的微服务架构设计 5

Zuul网关服务组件

  • 入站过滤器(Inbound Filter)可用于身份验证、路由和装饰请求。
  • 端点过滤器(Endpoint Filter)可用于返回静态资源或将请求路由到适当的Origin或应用程序API做进一步处理。
  • 出站过滤器(Outbound Filter)可用于跟踪指标、装饰对用户的响应或添加自定义标头。
  • Zuul集成了服务发现组件Eureka,从而能够发现新的应用程序API。
  • Zuul被广泛用于各种用途的流量路由任务上,例如启用新的应用程序API、负载测试、在负载很大的情况下路由到不同的服务端点上,等等。

3.2.2 应用程序API

应用程序API充当Netflix微服务的业务流程层(也称编排层)。这种API提供了一种逻辑,按所需顺序组装对底层微服务的调用,并带有来自其他数据存储的额外数据以构造适当的响应。Netflix团队花了很多时间设计应用程序API组件,因为它对应Netflix的核心业务功能。它还需要在高请求量下具有可扩展和高可用性。当前,应用程序API分为三类:用于非会员请求(例如注册、下单和免费试用等)的注册(Signup)API,用于搜索和发现请求的发现(Discovery)API,以及用于流视频和查看许可请求的播放API。图5提供了应用程序API的详细结构组件图。

全面解析Netflix的微服务架构设计 6

播放和发现应用程序API的分离

  • 在播放API实现的最新更新中,播放API和微服务之间的网络协议是gRPC/HTTP2,它“允许通过协议缓冲区定义RPC方法和实体,并自动以多种语言生成客户端库/SDK”。此项更改使应用程序API可以通过双向通信与自动生成的客户端进行适当集成,并“尽可能减少跨服务边界的代码重用”。
  • 应用程序API还提供了一种基于Hystrix命令的通用弹性机制,以保护其底层微服务。

由于应用程序API必须处理大量请求并构造适当的响应,因此其内部处理工作需要高度并行运行。Netflix团队发现正确的方法是同步执行和异步I/O相结合应用。

全面解析Netflix的微服务架构设计 7

应用程序API的同步执行和异步I/O

  • 来自API网关服务的每个请求都将放入应用程序API的网络事件循环(Network Event Loop)中处理;
  • 每个请求将被一个专用的线程处理程序阻止,该处理程序将Hystrix命令(如getCustomerInfo和getDeviceInfo等)放入传出事件循环(Outgoing Event Loop)中。传出事件循环是针对每个客户端设置的,并以非阻塞I/O运行。一旦调用的微服务完成或超时,上述专用线程将构造对应的响应。

3.2.3 微服务

按照Martin Fowler的定义,“微服务是一组小型服务,每个小服务都在自己的进程中运行,并使用轻量机制通信……”。这些小型程序可以独立部署或升级,并具有自己的封装数据。

Netflix上的微服务组件实现如图7所示。

全面解析Netflix的微服务架构设计 8

微服务的结构化组件

  • 微服务可以独立工作,也能通过REST或gRPC调用其他微服务。
  • 微服务的实现可以类似于图6中描述的应用程序API的实现:请求将被放入网络事件循环中,而来自其他被调用的微服务的结果将放入异步非阻塞I/O中的结果队列。
  • 每个微服务能拥有自己的数据存储和一些存放近期结果的内存缓存存储。EVCache是​​Netflix微服务缓存的主要选择。

3.2.4 数据存储

Netflix将其基础架构迁移到AWS云时,针对不同的用途使用了不同的数据存储(图8),包括SQL和NoSQL。

全面解析Netflix的微服务架构设计 9

部署在AWS上的Netflix数据存储

  • MySQL数据库用于电影标题管理和交易/下单目的。
  • Hadoop用于基于用户日志的大数据处理。
  • ElasticSearch为Netflix应用提供了标题搜索能力。
  • Cassandra是基于列的分布式NoSQL数据存储,可处理大量读取请求,而没有单点故障。为了优化大规模写请求的延迟,Netflix使用了Cassandra,因为它具有最终的一致性能力。

3.2.5 流处理管道

流处理数据管道(Stream Processing Data Pipeline)已成为Netflix业务分析和个性化推荐任务的数据骨干。它负责实时生成、收集、处理和汇总所有微服务事件,并将其移动到其他数据处理器上。图9展示了该平台的各个部分。

全面解析Netflix的微服务架构设计 10

Netflix的Keystone流处理平台

  • 这一流处理平台每天处理数以万亿计的事件和PB级的数据。随着订户数量的增加,它也会自动扩展。

  • 路由(Router)模块支持路由到不同的数据sink或应用程序上,而Kafka负责路由消息,并为下游系统提供缓冲。

  • 流处理即服务(SPaaS)使数据工程师可以构建和监视他们自定义的可管理流处理应用程序,而平台将负责可扩展性和运维。

3.3 Open Connect

Open Connect是一个全球内容交付网络(CDN),负责存储Netflix电视节目和电影并将其交付给全世界的订户。Netflix为了让人们想要观看的内容尽可能靠近他们想要观看的位置,而构建和运营了Open Connect这一高效率的网络。为了将观看Netflix视频的流量导向到客户的当地网络中,Netflix已与世界各地的互联网服务提供商(ISP)和互联网交换点(IX或IXP)合作,以在这些合作伙伴的网络内部部署称为Open Connect Appliances(OCA)的专用设备。

全面解析Netflix的微服务架构设计 11

将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地址的2个不同站点之间,OCA可以应用层填充(tier fill)流程,而不是常规的缓存填充。

全面解析Netflix的微服务架构设计 12

OCA之间的填充模式

4.设计目标

在前面的章节中,我详细介绍了为Netflix视频流业务提供支持的云架构及其组件。在本节和后续章节中,我想更深入地分析这种设计架构。我会从最重要的设计目标列表开始,如下所示:

  • 确保全球范围内流服务的高可用性。
  • 弹性处理网络故障和系统中断。
  • 在各种网络条件下,将每台受支持设备的流传输延迟降至最低。
  • 支持高请求量的可扩展性。

在下面的小节中,我将分析流服务的可用性及其对应的最佳延迟。第6节是关于弹性机制(例如混沌工程)的更深入分析,而第7节介绍了流服务的可扩展性。

4.1 高可用性

根据定义,系统的可用性是用一段时间内对请求的响应有多少次来衡量的,但不能保证响应包含了信息的最新版本。在我们的系统设计中,流服务的可用性是由后端服务和保存流视频文件的OCA服务器的可用性共同决定的。

后端服务的目标是通过缓存或某些微服务的执行来获取最接近特定客户端的健康OCA列表。因此,其可用性取决于涉及播放请求的众多组件:负载均衡器(AWS ELB)_代理服务器(API网关服务)、播放API、微服务的执行、缓存存储(EVCache)和数据存储(Cassandra):

  • 负载均衡器可以将流量路由到不同的代理服务器上以帮助防止负载超载,从而提高可用性。

  • 播放API通过Hystrix命令控制超时微服务的执行,从而防止级联故障影响其他服务。

  • 如果微服务对外部服务或数据存储的调用所花费的时间超出预期,则它可以使用缓存中的数据响应播放AI。

  • 缓存会被复制以加快访问速度。

当客户端从后端接收到OCA服务器列表时会在网络上探测这些OCA,并选择最佳的OCA进行连接。如果该OCA在流处理过程中超载或失败,则客户端将切换到另一个状态良好的OCA上,否则Platform SDK将请求其他OCA。因此,其可用性与ISP或IXP中所有可用OCA的可用性高度相关。

Netflix流服务的高可用性是以复杂的多区域AWS运维和服务,以及OCA服务器的冗余为代价的。

4.2 低延迟

流服务的等待时间主要取决于播放API能多快地解析健康的OCA列表,以及客户端与所选OCA服务器的连接健康水平。

正如我在应用程序API组件部分中所述,播放API不会永远等待微服务的执行,因为它使用Hystrix命令来控制获取到结果之前要等待的时间,一旦超时就会从缓存获取非最新数据。这样做可以将延迟控制在可接受的水平上,还能避免级联故障影响更多服务。

如果当前选定的OCA服务器出现网络故障或超载,则客户端将立即切换到其他具有最可靠网络连接的OCA服务器上。如果发现网络连接质量下降,它也可以降低视频质量以使其与网络质量相匹配。

5.权衡

经过认真考虑,在上述系统设计中已经做出了两个重要的权衡:

  • 用一致性换取低延迟
  • 用一致性换取高可用性

该系统后端服务的架构设计选择了用一致性来换取低延迟。播放API可以从EVCache存储或最终一致的数据存储(如Cassandra)中获取过时的数据。

类似地,所谓用一致性换取高可用性的权衡是说,系统希望以可接受的延迟发起响应,而不会对像Cassandra这样的数据存储中的最新数据执行微服务。

在可扩展性和性能之间还存在不完全相关的权衡。在这种权衡下,通过增加实例数量来处理更多负载来提高可扩展性,可能会导致系统达不到预期的性能提升水平。对于那些无法在可用worker之间很好地平衡负载的设计架构来说,这可能是个问题。但是,Netflix通过AWS自动扩展解决了这一矛盾。我们将在第7节中具体讨论这个解决方案。

6.弹性

从迁移到AWS云的那一天起,设计一套能够从故障或停机中自我恢复的云系统就一直是Netflix的长期目标。该系统已解决的一些常见故障如下:

解析服务依赖项时失败。

执行微服务时的失败,导致级联失败影响其他服务。

由于过载导致无法连接到某个API上。

连接到实例或服务器(如OCA)时失败。

为了检测并解决这些故障,API网关服务Zuul提供了一些内置功能,如自适应重试和限制对应用程序API的并发调用等。反过来说,应用程序API使用Hystrix命令来使对微服务的调用超时,以停止级联故障并将故障点与其他服务隔离开来。

Netflix技术团队也以其在混沌工程上的实践而闻名。这个想法是将伪随机错误注入生产环境,并构建解决方案以自动检测、隔离这类故障,并从中恢复。这些错误可能会增加执行微服务的响应的延迟、杀死服务、停止服务器或实例,甚至可能导致整个区域的基础架构瘫痪。通过有目的地使用检测和解决此类故障的工具,将现实的生产故障引入受监控的环境,Netflix可以在这类缺陷造成较大问题之前提早发现它们。

7.可扩展性

在本节中,我将介绍水平扩展、并行执行和数据库分区这些Netflix的流服务可扩展性要素。缓存和负载均衡等要素也有助于提高可扩展性,它们已在第4节中提到了。

首先,AWS自动扩展(Auto Scaling)服务提供了Netflix上EC2实例的水平扩展能力。当请求量增加时,这个AWS服务将自动启动更多弹性实例,并关闭未使用的实例。更具体地说,在成千上万个此类实例的基础上,Netflix构建了一个开源容器管理平台Titus,其每周可运行约300万个容器。同样,图2架构中的任何组件都可以部署在容器内。此外,Titus允许容器运行在全球各大洲的多个区域内。

其次,第3.2.2节中应用程序API或微服务的实现还允许在网络事件循环和异步传出事件循环上并行执行任务,从而提高了可扩展性。

最后,宽列存储(如Cassandra)和键值对象存储(如ElasticSearch)还提供了高可用性和高可扩展性,同时没有单点故障。

8.总结

这篇研究描绘了Netflix流服务的整体云架构图景。本文还从可用性、延迟、可扩展性和对网络故障或系统中断的适应性方面分析了相应的设计目标。

总的来说,Netflix的云架构已经过了其生产系统的验证,可以为在数千个虚拟服务器上运行的数百万个订户提供服务;该架构还通过与AWS云服务的集成在全球范围内提供了高可用性、最佳延迟、强大的可扩展性以及对网络故障和系统故障的恢复能力。本文提到的大多数架构和组件都是通过互联网上的可信在线资源学习总结出来的。尽管网上没有太多资源能直接介绍这些微服务的内部实现,以及监视其性能表现的工具和系统,但本文的研究成果可以作为构建典型生产系统的参考实现。

英文原文:

A Design Analysis of Cloud-based Microservices Architecture at Netflix