我们很高兴地宣布Netflix的云网关Zuul 2的开源。我们在Netflix使用Zuul 2作为进入Netflix云基础架构的所有请求的前门。Zuul 2显着改进了架构和功能,使我们的网关能够处理,路由和保护Netflix的云系统,并有助于为1.25亿会员提供最佳体验。Netflix的Cloud Gateway团队运行和运营超过80个Zuul 2集群,向大约100个(并且不断增长的)后端服务集群发送流量,每秒超过100万个请求。几乎所有这些流量都来自客户设备和浏览器,可以实现您可能熟悉的发现和回放体验。
这篇文章将概述Zuul 2,提供我们今天发布的一些有趣功能的详细信息,并讨论我们用Zuul 2构建的其他一些项目。

Zuul 2如何运作

对于上下文,这是Zuul 2架构的高级图:
0_ycjEWsSKCaPemEg3_.png
过滤器正面和背面的Netty处理程序主要负责处理网络协议,Web服务器,连接管理和代理工作。随着那些内部工作被抽象掉,过滤器完成了所有繁重的工作。入站过滤器在代理请求之前运行,可用于身份验证,路由或装饰请求。端点过滤器可以用于返回静态响应,也可以将请求代理到后端服务(或者我们称之为源)。出站过滤器在返回响应后运行,可用于gzipping,metrics或添加/删除自定义标头等内容。
Zuul的功能几乎完全取决于您在每个过滤器中添加的逻辑。这意味着您可以在多个上下文中部署它,并根据其运行的配置和过滤器解决不同的问题。
我们在所有外部流量的入口点使用Zuul进入Netflix的云服务,我们也开始使用它来路由内部流量。我们部署相同的核心,但功能大幅减少(即更少的过滤器)。这使我们能够利用内部流量的负载平衡,自助服务路由和弹性功能。

开源

今天运行的Zuul代码是Zuul最稳定和最具弹性的版本。进化和重构代码库的各个阶段都带来了好处,我们很高兴与您分享。
今天我们发布了许多核心功能。以下是我们最为兴奋的事情:

服务器协议

  • HTTP / 2  - 对入站HTTP / 2连接的完整服务器支持
  • 相互TLS  - 允许在更安全的场景中运行Zuul

    弹性特征

  • 自适应重试  - 我们在Netflix上使用的核心重试逻辑,以提高我们的弹性和可用性

  • Origin Concurrency Protection  - 可配置的并发限制,以保护您的起源免于过载并保护Zuul背后的其他来源

    运营特色

  • 请求Passport  - 跟踪每个请求的所有生命周期事件,这对于调试异步请求非常有用

  • 状态类别  - 对比HTTP状态代码更精细的请求的可能成功和失败状态的枚举
  • 请求尝试  - 跟踪代理尝试和每个的状态,对于调试重试和路由特别有用

我们还在研究即将推出的一些功能,包括:

  • Websocket / SSE  - 支持旁道推送通知
  • 限制和速率限制  - 防止恶意客户端连接和请求,帮助抵御容量攻击
  • 掉电滤波器  - 用于在Zuul过载时禁用某些CPU密集型功能
  • 可配置路由  - 基于文件的路由配置,而不必在Zuul中创建路由过滤器

我们很乐意听取您的意见,并了解Zuul的所有新的和有趣的应用。有关入门的说明,请访问我们的维基页面

在Netflix上利用Zuul 2

在内部,有几个主要功能我们一直在努力,但还没有开源。每个人都应该拥有自己的博客文章,但让我们简要介绍一下。

自助服务路由

我们的合作伙伴使用最广泛的功能是自助服务路由。我们为用户提供应用程序和API,以根据请求URL,路径,查询参数或标头中的任何条件创建路由规则。然后,我们将这些路由规则发布到所有Zuul实例。
主要用例是将流量路由到特定测试或临时群集。但是,实际生产流量有很多用例。例如:

  • 需要对其流量进行分片的服务会创建将某些路径或前缀映射到不同来源的路由规则
  • 开发人员通过创建将新主机名映射到其新源的路由来加载新服务
  • 开发人员通过将一定百分比的现有流量路由到一个小型集群来运行负载测试,并确保应用程序在负载下正常降级
  • 通过创建逐步映射流量的规则(一次一条路径),重构应用程序的团队可以缓慢地迁移到新的原点
  • 团队通过将一小部分流量发送到运行新构建的检测集群来测试更改(金丝雀测试)
  • 如果团队需要测试需要在其新构建上连续多次请求的更改,他们会运行粘性金丝雀测试,将相同的用户路由到他们的新构建中很短的时间
  • 安全团队根据所有Zuul集群中的路径或标头规则创建拒绝“错误”请求的规则

正如您所看到的,我们广泛使用自助服务路由,并且正在增加路由的可定制性和范围,以允许更多用例。

负载均衡以实现弹性

我们所做的另一个主要功能是使源的负载平衡更加智能化。我们能够绕过故障,缓慢,GC问题以及在运行大量节点时经常出现的各种其他事情。这项工作的目标是提高所有Netflix服务的弹性,可用性和服务质量。
我们处理了几个案例:

冷实例

当新的原始实例启动时,我们会在一段时间内向他们发送减少的流量,直到它们被预热为止。这是我们在具有大型代码库和巨大的元空间使用的应用程序中观察到的问题。这些应用程序需要花费大量时间来编写代码并准备好处理大量流量。
我们通常还会将流量偏向于较旧的实例,如果我们碰巧遇到了节流的冷实例,我们总是可以在温暖的情况下重试。这使我们的可用性提高了一个数量级。

高错误率

错误始终发生并且由于各种原因,无论是由于代码中的错误,错误的实例还是设置的无效配置属性。幸运的是,作为代理,我们可以可靠地检测错误 - 我们得到5xx错误或者服务存在连接问题。
我们跟踪每个来源的错误率,如果错误率足够高,则意味着整个服务都有问题。我们限制从设备重试并禁用内部重试以允许服务恢复。此外,我们还会跟踪每个实例的连续故障,并在一段时间内将不良故障列入黑名单。

重载的实例

通过上述方法,我们可以减少群集中限制或拒绝连接的服务器的流量,并通过在其他服务器上重试这些失败的请求来减轻影响。
我们现在推出了另一种方法,我们的目标是避免首先使服务器过载。这是通过允许来源向Zuul发信号通知其当前利用率来实现的,Zuul随后将其用作其负载平衡选择中的一个因素 - 从而降低错误率,重试和延迟。
起源为所有响应添加标题,说明它们的利用率百分比,以及它们希望在整个群集中具有的目标利用率。计算百分比完全取决于每个应用程序,工程师可以使用最适合他们的任何度量标准。与我们试图提出一种通用的方法相比,这允许一般的解决方案。
有了这个功能,我们为每个实例分配一个分数(实例利用率和上面的其他因素的组合),并选择两个负载均衡选择。

异常检测和上下文警报

随着我们从少数几个起源发展到一个新的世界,任何人都可以快速启动集装箱集群并将其置于Zuul之后,我们发现需要自动检测并查明原点故障。
Mantis实时事件流的帮助下,我们构建了一个异常检测器,可以汇总每个服务的错误率,并在服务出现问题时实时通知我们。它会占用给定时间窗口中的所有异常,并创建所有起源的时间表。然后,我们创建一个上下文警报电子邮件,其中包含受影响事件和服务的时间表。这允许操作员快速关联这些事件并定位自己以调试特定的应用程序或功能,并最终找到根本原因。
实际上,我们扩展它以向原始团队自己发送通知非常有用。除了Zuul之外,我们还添加了更多内部应用程序,并且可以构建更广泛的事件时间表。这在生产事故期间提供了巨大的帮助,并帮助操作员在问题进入大规模停电之前快速检测并修复问题。
我们希望尽可能多地开源上述功能。继续观看科技博客,了解更多信息。如果您想帮助我们解决这些问题,请查看我们的工作网站