Netflix 如何在 7 分钟内完成故障转移

Netflix 将响应中断的时间从 45 分钟缩短到 7 分钟,且没有增加额外成本。
587 位读者喜欢这篇文章。
Opensource.com CFP and September preview

Florida Memory。由 Opensource.com 修改。CC BY-SA 4.0

2012 年冬季,由于美国东部地区 AWS Elastic Load Balancer 服务出现问题,Netflix 遭遇了一次长时间中断,持续了 7 个小时。(Netflix 在亚马逊网络服务 [AWS] 上运行——我们没有自己的数据中心。您与 Netflix 的所有交互都由 AWS 提供服务,除了视频的实际流媒体播放。一旦您点击“播放”,实际的视频文件将从我们自己的 CDN 提供。)在中断期间,进入美国东部的所有流量都无法到达我们的服务。

为了防止这种情况再次发生,我们决定构建一个区域故障转移系统,以应对底层服务提供商的故障。故障转移是一种保护计算机系统免受故障的方法,其中备用设备在主系统发生故障时自动接管。

区域故障转移降低了风险

我们扩展到总共三个 AWS 区域:美国两个(美国东部和美国西部)和欧盟一个(欧盟)。我们预留了足够的容量来执行故障转移,以便我们可以承受单个区域的中断。

典型的故障转移看起来像这样

  1. 意识到其中一个区域出现问题。
  2. 扩展两个救援区域。
  3. 将一些来自故障区域的流量代理到救援区域。
  4. 将 DNS 从问题区域更改为救援区域。

让我们探索每个步骤。

1. 识别问题

我们需要指标,最好是单一指标,可以告诉我们系统的健康状况。在 Netflix,我们使用一个称为每秒流媒体启动次数(简称 SPS)的业务指标。这是成功开始流式传输节目的客户端数量的计数。

我们按区域划分了此数据,在任何给定时间,我们可以绘制每个区域的 SPS 数据,并将其与前一天和前一周的 SPS 值进行比较。当我们注意到 SPS 图表中的下降时,我们知道我们的客户无法开始流式传输节目,因此我们遇到了麻烦。

问题不一定是云基础设施问题。它可能是构成 Netflix 生态系统的数百个微服务之一中的错误代码部署、海底电缆断裂等。我们可能不知道原因;我们只知道出了问题。

如果仅在一个区域观察到 SPS 下降,那么它非常适合区域故障转移。如果在多个区域观察到下降,我们就倒霉了,因为我们一次只有足够的容量来疏散一个区域。这正是我们一次在一个区域错开部署微服务的原因。如果部署有问题,我们可以立即疏散并在以后调试问题。同样,我们希望避免在问题会跟随流量重定向时进行故障转移(就像 DDoS 攻击中发生的那样。)

2. 扩展救援区域

一旦我们确定了有问题的区域,我们应该准备好其他区域(“救援区域”)来接收来自故障区域的流量。在我们打开消防水管之前,我们需要适当地扩展救援区域中的堆栈。

在这种情况下,适当的扩展意味着什么?Netflix 的流量模式在一天中不是静态的。我们有高峰观看时间,通常在下午 6-9 点左右。但是下午 6 点在世界各地到达的时间不同。美国东部的高峰流量比美国西部提前三个小时,而美国西部比欧盟地区落后八个小时。

当我们故障转移美国东部时,我们将来自美国东部的流量发送到欧盟,并将来自南美的流量发送到美国西部。这是为了减少延迟并为我们的客户提供最佳体验。

考虑到这一点,我们可以使用线性回归来预测在一天中的那个时间(和一周中的某天)将路由到救援区域的流量,使用每个微服务的历史扩展行为。

一旦我们确定了每个微服务的适当大小,我们就通过设置每个集群的期望大小来触发每个微服务的扩展,然后让 AWS 完成它的魔法。

3. 代理流量

现在微服务集群已经扩展,我们开始将来自故障区域的流量代理到救援区域。Netflix 构建了一个高性能、跨区域的边缘代理,名为 Zuul,我们已经将其开源

这些代理服务旨在验证请求、进行负载脱落、重试失败的请求等。Zuul 代理也可以进行跨区域代理。我们使用此功能将少量流量从受影响的区域路由出去,然后逐步增加重新路由的流量量,直到达到 100%。

这种渐进式代理允许我们的服务使用其扩展策略来执行处理传入流量所需的任何反应性扩展。这是为了补偿在我们进行扩展预测的时间和扩展每个集群所需的时间之间流量量发生任何变化。

Zuul 在此时承担了繁重的工作,将来自故障区域的所有传入流量路由到健康区域。但是,现在是完全放弃受影响区域的时候了。这就是 DNS 切换发挥作用的地方。

4. 切换 DNS

故障转移的最后一步是更新指向受影响区域的 DNS 记录,并将它们重定向到健康区域。这将完全将所有客户端流量从故障区域移开。任何未过期其 DNS 缓存的客户端仍将由受影响区域中的 Zuul 层路由。

这就是故障转移过去在 Netflix 的工作方式的背景信息。此过程完成需要很长时间——大约 45 分钟(在顺利的情况下)。

通过闪亮的新流程加速响应

我们注意到,大部分时间(大约 35 分钟)都花在等待救援区域扩展上。即使 AWS 可以在几分钟内为我们配置新实例,但在 discovery 中注册 UP 之前,启动服务、进行即时预热和处理其他启动任务仍然主导了扩展过程。

我们认为这太长了。我们希望我们的故障转移在 10 分钟内完成。我们希望在不增加服务所有者运营负担的情况下做到这一点。我们也希望保持成本中性。

我们在所有三个区域都预留了容量来吸收故障转移流量;如果我们已经为所有这些容量付费,为什么不使用它呢?因此开始了 Nimble 项目。

我们的想法是为每个微服务维护一个热备用实例池。当我们准备好进行故障转移时,我们可以简单地将我们的热备用实例注入到集群中以接收实时流量。

未使用的预留容量称为低谷。Netflix 的一些团队使用一些低谷容量来运行批处理作业,因此我们不能简单地将所有可用的低谷变成热备用。相反,我们可以为我们运行的每个微服务维护一个影子集群,并为该影子集群配备足够的实例,以应对该时间段的故障转移流量。其余实例可供批处理作业随意使用。

在故障转移时,我们没有采用触发 AWS 为我们配置实例的传统扩展方法,而是将来自影子集群的实例注入到活动集群中。此过程大约需要四分钟,而过去需要 35 分钟。

由于我们的容量注入非常迅速,因此我们不必谨慎地通过代理移动流量以允许扩展策略做出反应。我们可以简单地切换 DNS 并打开闸门,从而在中断期间节省更多宝贵的时间。

我们在影子集群中添加了过滤器,以防止暗实例报告指标。否则,它们会污染指标空间并混淆正常的运行行为。

我们还通过修改我们的发现客户端,阻止影子集群中的实例在发现中注册为 UP。这些实例将继续保持黑暗状态(双关语完全有意),直到我们触发故障转移。

现在我们可以在七分钟内完成区域故障转移。由于我们利用了现有的预留容量,因此我们没有产生任何额外的基础设施成本。协调故障转移的软件由一个由三名工程师组成的团队用 Python 编写。


要了解有关 Netflix 如何使用 Python 的更多信息,请参加 Amjith Ramanujam 的演讲,Netflix 如何在 7 分钟内完成故障转移,在 PyCon 克利夫兰 2018

标签
User profile image.
Amjith Ramanujam 是 Netflix 的高级软件工程师。他的团队负责在极端逆境中保持 Netflix 服务的运行。换句话说,他的团队负责进行区域故障转移。在他的业余时间,他编写现代 CLI 工具。他是 pgcli 和 mycli 的创建者。您应该在 Twitter 上向他打招呼。

评论已关闭。

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 获得许可。
© . All rights reserved.