疯狂创客圈为小伙伴奉上以下珍贵的学习资源:


疯狂创客圈 高质量 博文 推荐

高并发 必读 的精彩博文
nacos 实战(史上最全) sentinel (史上最全+入门教程)
Zookeeper 分布式锁 (图解+秒懂+史上最全) Webflux(史上最全)
SpringCloud gateway (史上最全)TCP/IP(图解+秒懂+史上最全)
10分钟看懂, Java NIO 底层原理Feign原理 (图解)
大厂必备之:Reactor模式更多精彩博文 … 请参见【 疯狂创客圈 高并发 总目录

1 概述

数年来,Netflix 一直是全球体验最好的在线订阅制视频流媒体服务,其流量占全球互联网带宽容量的 15%以上。 在2019 年,Netflix 已经有 1.67 亿名订阅用户,平均每个季度新增 500 万订户,服务覆盖全球 200 多个国家 / 地区。

Netflix 用户每天在 4000 多部电影和 47000 集电视剧上花费超过 1.65 亿小时的时间。从工程角度看,这些统计数据向我们展示了 Netflix 的技术团队设计出了多么优秀的视频流系统,而这套系统具有很高的可用性和可扩展性,能为全球用户提供服务。

实际上,Netflix的技术团队是花了超过 8 年时间方打造出今天这样强大的 IT 系统。

以上内容来源:

medium的博文

Netflix 的基础架构转型始于 2008 年 8 月,那时这家公司的数据中心遇到了Web服务中断的故障,导致整个 DVD 租赁服务关闭3天,损失较大。Netflix 的技术团队如梦方醒,它需要一个没有单点故障的更可靠的基础架构。因此技术团队管理层做出两个重要决定,将 IT 基础架构从自己的IDC迁移到公共云上,通过改造成微服务架构,用较小的易管理软件组件替换单体程序。

以上这两个决定为今天 Netflix 的成功打下了坚实基础。

任何一个普通的服务,放到 Netflix 的大规模集群(上万台机器)里运行,如果不做特别处理,会发生各种各样的问题,以实现一个电影推荐的服务为例,传统方案:

img

在传统的方案里,你会使用固定 DNS 域名解析服务,将一组固定的 IP 放在负载均衡的列表里。服务注册和发现都是写在配置文件里,一旦服务挂掉了,依赖于这个服务的其他服务都会受到影响,传统的办法只能新起一台服务器,然后去改变其他机器的配置文件,并重启关联的服务。

在小的集群里这种方式或许可以忍受,但在上万台服务器的集群里,管理500多种服务的时候,情况将变得非常复杂,Netflix 通过多年的实践,贡献出了很多开源项目,例如:Eureka, Hystrix, Feign,Ribbon 等等, 来解决大规模集群里服务管理的问题。

说明:Netflix 的微服务有500多种,这些微服务的实例运行在上万台的机器上,有上万个实例。

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

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

2 架构

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 流程的工作机制:

img

用于流视频的 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 可能使用的微服务架构,我从一些在线资源中总结出了这些架构形态:

img基于多种后端架构参考:

  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 展示了一个典型的客户端结构组件。

img

客户端应用组件

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

3.2 后端

API 网关服务

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

imgZuul 网关服务组件

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

应用程序 API

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

img

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

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

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

img

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

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

微服务

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

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

img微服务的结构微服务化组件

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

数据存储

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

img

部署在 AWS 上的 Netflix 数据存储

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

流处理管道

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

imgNetflix 的 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)的专用设备。

img

将 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)流程,而不是常规的缓存填充。

    img

    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 线上发布的方式:

金丝雀、蓝绿、红黑灰发布

8.1发布之痛

相信每个程序员都曾经经历过,或正在经历过发布的痛苦,每个发布日的夜晚通常是灯火通明。在现在互联网公司较高的发布频率之下更是放大了这种痛苦,多少正值青春年华的程序员为此白了发、秃了头!让程序员经历发布痛苦的原因有很多,其中之一就是发布方式。
发布造成系统故障影响系统可用性的最大原因之一。因此大多数的公司会选择在用户量最小的深夜进行发布,这就造成了每到发布日就有一大堆黑眼圈的程序员熬夜坐等发布,但其实有了一些好的发布方式也许就不必如此。
我曾经带过两家公司,这两家公司团队的对于发布时间的看法则孑然不同,第一家公司的总是担心发布会对用用户造成影响,因此每次发布都会选择深夜进行发布。而另一家公司则认为应该在用户流量最大的时候进行发布,这样系统问题则可以尽早的暴露出来。造成这两种的结果我分析有很多原因。开发人员信心、交付质量、资源工具、发布方式…我们今天就来看看一些常用的发布方式。

8.2 常用的发布方式

蛮力发布

顾名思义,这种方式简单而粗暴!直接将新的版本覆盖掉老的版本。其优点就是简单而且成本较低,但缺点同样很明显,就是发布过程中通常会导致服务中断进而导致用户受到影响,这种方式比较适应于开发环境或者测试环境或者是公司内部系统这种对可用性要求不高的场景,有些小的公司资源稀缺(服务器资源,基础设施等)的时候也会采用这种方式。比如小公司开始的规模较小的时候,通常会选择一个夜深人静、访问量小的时候,悄悄地发布。
蛮力发布

金丝雀发布

金丝雀发布是灰度发布的一种。灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式。即在发布过程中一部分用户继续使用老版本,一部分用户使用新版本,不断地扩大新版本的访问流量。最终实现老版本到新版本的过度。由于金丝雀对瓦斯极其敏感,因此以前旷工开矿下矿洞前,先会放一只金丝雀进去探是否有有毒气体,看金丝雀能否活下来,金丝雀发布由此得名。
金丝雀发布
发布过程中,先发一台或者一小部分比例的机器作为金丝雀,用于流量验证。如果金丝雀验证通过则把剩余机器全部发掉。如果金丝雀验证失败,则直接回退金丝雀。金丝雀发布的优势在于可以用少量用户来验证新版本功能,这样即使有问题所影响的也是很小的一部分客户。如果对新版本功能或性能缺乏足够信心那么就可以采用这种方式。这种方式也有其缺点,金丝雀发布本质上仍然是一次性的全量发布,发布过程中用户体验并不平滑,有些隐藏深处的bug少量用户可能并不能验证出来问题,需要逐步扩大流量才可以。

滚动发布

滚动发布是在金丝雀发布基础上进行改进的一种发布方式。相比于金丝雀发布,先发金丝雀,然后全发的方式,滚动发布则是整个发布过程中按批次进行发布。每个批次拉入后都可作为金丝雀进行验证,这样流量逐步放大直至结束。滚动发布
这种方式的优点就是对用户的影响小,体验平滑,但同样也有很多缺点,首先就是发布和回退时间慢,其次发布工具复杂,负载均衡设备需要具有平滑的拉入拉出能力,一般公司并没有资源投入研发这种复杂的发布工具。再者
发布过程中新老版本同时运行,需要注意兼容性问题。

蓝绿部署

蓝绿部署,是采用两个分开的集群对软件版本进行升级的一种方式。它的部署模型中包括一个蓝色集群 Group1 和一个绿色集群 Group2,在没有新版本上线的情况下,两个集群上运行的版本是一致的,同时对外提供服务。蓝绿部署
系统升级时,蓝绿部署的流程是:

  • 从负载均衡器列表中删除集群Group1,让集群 Group2 单独提供服务。
  • 在集群 Group1 上部署新版本。
  • 集群 Group1 升级完毕后,把负载均衡列表全部指向 Group1,并删除集群 Group2 ,由 Group1 单独提供服务。
  • 在集群 Group2 上部署完新版本后,再把它添加回负载均衡列表中。

这样,就完成了两个集群上所有机器的版本升级。

蓝绿部署的优点是升级和回退速度非常快,缺点是全量升级,如果V2版本有问题,对用户影响大再者由于升级过程中会服务器资源会减少一半,有可能产生服务器过载问题,因此这种发布方式也不适用于在业务高峰期使用。

红黑发布

与蓝绿部署类似,红黑部署也是通过两个集群完成软件版本的升级。当前提供服务的所有机器都运行在红色集群 Group1 中,当需要发布新版本的时候,具体流程是这样的:

  • 先申请一个黑色集群 Group2 ,在 Group2 上部署新版本的服务;

  • 等到 Group2 升级完成后,我们一次性地把负载均衡全部指向 Group2 ;

  • 把 Group1 集群从负载均衡列表中删除,并释放集群 Group1 中所有机器。这这样就完成了一个版本的升级。

可以看到,与蓝绿部署相比,红黑部署获得了两个收益:一是,简化了流程;二是,避免了在升级的过程中,由于只有一半的服务器提供服务,而可能导致的系统过载问题。但同样也存在全量升级对用户的影响问题,也带来了一个新的问题,就是发布过程中需要两倍的服务器资源。
红黑发布.png

功能开关

这种发布方式是利用代码中的功能开关来控制发布逻辑,是一种相对比较低成本和简单的发布方式。研发人员可以灵活定制和自助完成的发布方式。这种方式通常依赖于一个配置中心系统,当然如果没有,可以使用简单的配置文件。

功能开关.png
应用上线后,开关先不打开,只待一声令下,可以全量打开开关,也可以按照某种维度(公司ID,用户ID等)分批打开开关进行流量验证,如果有问题,则随时关闭开关。
这种方式的优势在于升级切换和回退速度非常快,而且相对于复杂的发布工具,成本较为低廉。但是也有很大的不足之处,就是开关本身也是代码,而且是与业务无关的代码,对代码的侵入性较高,也必须定期清理老版本的逻辑,使得维护成本增加。

发布方式小结

每种发布方式各有其优缺点。但其实在真正实践过程中这些发布方式往往是根据具体的情况来结合使用的。主要可以通过升级回退速度、成本、对用户影响三个方面来考虑。

8.3 Eureka 红黑发布

Eureka 解决的问题

Eureka 服务器是服务的注册中心,它能提高大规模集群环境里服务发现的容错性和可用性。并且可以解决跨数据中心之间的服务注册和发现的问题。

Netflix 推荐在每个 Region 搭建一个 Eureka 集群,每个 Region 里的可用区至少有一个 Eureka Server,这样可以保证任意一个可用区的服务注册信息都会被复制到各个可用区,实现服务信息的高可用。在任意可用区的客户端都可以访问到服务的注册信息。客户端在访问服务器之后会在本地缓存服务的信息,并且定期(30秒)刷新服务的状态。

如果在集群内有大面积的网络故障时(例如由于交换机故障导致子网之间无法通信),Eureka 会进入自我保护模式,每个Eureka节点会持续的对外提供服务(注:ZooKeeper不会):接收新的服务注册同时将它们提供给下游的服务发现请求。这样就可以实现在同一个子网中(Same side of partition),新发布的服务仍然可以被发现与访问。

在 Eureka V1.0的版本里,Eureka 之间的数据同步是全量同步,每个客户端都有 Eureka 集群里所有服务的信息,在 V2.0的版本里,将支持客户端偏好的服务信息同步。同时也会增强 Eureka 的读写分离和高可用性。

有了 Eureka,Netflix 如何做红黑发布?

Netflix 发布的方式是红黑发布。如果监控到线上部署的服务有问题,按传统方式回滚一个服务需要5-15分钟。而 Netflix 使用 Eureka 能够动态的下线/上线一个服务。

服务分两种:REST 服务和非 REST 服务。如果下线的服务是 REST 服务,那么情况比较简单,通过 Eureka 可以实时的实现服务的下线和上线。

eureka下线和上线操作(可以通过postman和soapui或者其他http工具来发送命令):

微服务实例下线调用方式:PUT
http://ip:8810/eureka/apps/USER-SERVICE/192.168.1.9:user-service:8086/status?value=OUT_OF_SERVICE

微服务实例上线调用方式:PUT
http://ip:8810/eureka/apps/USER-SERVICE/192.168.1.9:user-service:8086/status?value=UP

Eureka会与Asgard交互 ,完成红黑发布:

作为与Netflix Asgard一起的红黑部署 - Asgard一个让云部署更方便的开源服务。Eureka会与Asgard交互,让应用在新/老版本部署切换,让故障处理更快速和无缝 - 尤其是当启动100个实例部署时要花费很长时间的时候。

来源:https://github.com/Netflix/eureka/wiki/Eureka-at-a-glance

如果服务是非 REST 服务,例如执行 Batching 任务或者快服务的 Transaction 等等,就不能简单的标记服务下线,借助于 Spring 提供的 EventListener (事件监听器),Eureka 可以传递
EurekaStatusChangeEvent 事件,帮助开发者在这个事件监听器里去做对应的服务下线处理。

Netflix 在实现红黑发布的时候,会先将一部分的服务动态下线,如果这些服务有一些 Batching 任务,则通过事件监听器停掉这些任务。

Netfix在每个区域(region)都会有一个eureka集群,它只知道关于这个区域内的实例信息。每个zone都至少也有一个eureka服务器来处理zone级别容灾。

服务注册在Eureka上并且每30秒发送心跳来续命。如果一个客户端在几次内没有刷新心跳,它会在90秒后被移出服务器注册信息。注册信息和刷新信息会在整个eureka集群的节点进行复制。任何zone的客户端都可看到注册信息(每30秒发生)去定位他们的服务(可能会在任何zone)并做远程调用。

9 总结

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

总体来说,Netflix 的云架构已经过了其生产系统的验证,可以为在数千个虚拟服务器上运行的数百万个订户提供服务;该架构还通过与 AWS 云服务的集成在全球范围内提供了高可用性、最佳延迟、强大的可扩展性以及对网络故障和系统故障的恢复能力。

本文提到的大多数架构和组件都是通过互联网上的可信在线资源学习总结出来的。尽管网上没有太多资源能直接介绍这些微服务的内部实现,以及监视其性能表现的工具和系统,但本文的研究成果可以作为构建典型生产系统的参考实现。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐