弃用 Nginx,他们选择这款工具!

Cloudflare公司去年宣布弃用Nginx,转用自研的新一代反向代理服务Pingora,并号称比nginx更快、更高效、更安全,下面通过Cloudfare官方网站的一篇文章来了解下Pingora比Nginx强在哪里 。简介今天 , 我们很高兴有机会在此介绍 Pingora,这是我们使用 Rust 在内部构建的新 HTTP 代理,它每天处理超过 1 万亿个请求,提高了我们的性能,并为 Cloudflare 客户带来了许多新功能,同时只需要我们以前代理基础架构的三分之一的 CPU 和内存资源 。
随着 Cloudflare 规模的扩大,我们已经超越了 NGINX 的处理能力 。多年来它一直运作良好,但随着时间的推移,它在我们规模上的局限性意味着我们有必要构建一些新的东西 。我们无法再获得我们所需要的性能,NGINX 也没有我们在非常复杂的环境中所需要的功能 。
许多 Cloudflare 客户和用户使用 Cloudflare 全球网络作为 HTTP 客户端(例如 Web 浏览器、应用程序、物联网设备等)和服务器之间的代理 。过去,对于浏览器和其他用户代理如何连接到我们的网络,我们已进行过许多讨论,我们开发了很多技术并实施了新协议(参见 QUIC 和 http2 优化)来使这段连接更高效 。
今天,我们将关注这个等式的另一部分:代理我们的网络和互联网上服务器之间的流量的服务 。这个代理服务为我们的 CDN、Workers fetch、Tunnel、Stream、R2 以及许多其他功能和产品提供了动力 。
让我们研究为什么我们选择取代我们的旧版服务以及 Pingora 的开发过程,这是我们专门为 Cloudflare 的客户用例和规模而设计的新系统 。
为什么要再建一个代理这些年来,我们对 NGINX 的使用遇到了限制 。对于部分限制 , 我们进行了优化或选择绕过它们 。但另一些限制则更难克服 。
架构的限制损害了性能
NGINX worker(进程)架构对于我们的用例而言存在操作缺陷,这会损害我们的性能和效率 。
首先,在 NGINX 中,每个请求只能由单个 worker 处理 。这会导致所有 CPU 内核之间的负载不平衡,从而导致速度变慢 。
由于这种请求进程锁定效应,执行 CPU 繁重或阻止 IO 任务的请求可能会减慢其他请求的速度 。正如这些博客文章所表明的那样,我们已经花了很多时间来解决这些问题 。
对于我们的用例来说,最关键的问题是糟糕的连接重用 。我们的机器与原始服务器建立 TCP 连接,以代理 HTTP 请求 。连接重用通过重用之前从连接池建立的连接,跳过新连接所需的 TCP 和 TLS 握手,来加快请求的 TTFB(首字节时间) 。
但是 , NGINX 连接池与单个 worker 相对应 。当请求到达某个 worker 时 , 它只能重用该 worker 内的连接 。当我们添加更多 NGINX worker 以进行扩展时,我们的连接重用率会变得更差,因为连接分散在所有进程的更多孤立的池中 。这导致更慢的 TTFB 以及需要维护更多连接,进而消耗我们和客户的资源(和金钱) 。

弃用 Nginx,他们选择这款工具!

文章插图
正如在过去的博客文章中所提到的,我们为其中一些问题提供了解决方法 。但如果我们能够解决根本问题:worker/进程模型,我们将自然而然地解决所有这些问题 。
有些类型的功能难以添加
NGINX 是一个非常好的 Web 服务器、负载均衡器或简单的网关 。但 Cloudflare 的作用远不止于此 。我们过去常常围绕 NGINX 构建我们需要的所有功能,但要尽量避免与 NGINX 上游代码库有太多分歧,这并不容易 。
例如,当重试请求/请求失败时,有时我们希望将请求发送到具有不同请求标头集的不同源服务器 。但 NGINX 并不允许执行此操作 。在这种情况下 , 我们需要花费时间和精力来解决 NGINX 的限制 。
同时,我们被迫使用的编程语言并没有帮助缓解这些困难 。NGINX 纯粹是用 C 语言编写的,这在设计上不是内存安全的 。使用这样的第 3 方代码库非常容易出错 。即使对于经验丰富的工程师来说,也很容易陷入内存安全问题,我们希望尽可能避免这些问题 。
我们用来补充 C 语言的另一种语言是 Lua 。它的风险较?。?但性能也较差 。此外 , 在处理复杂的 Lua 代码和业务逻辑时,我们经常发现自己缺少静态类型 。
而且 NGINX 社区也不是很活跃,开发往往是“闭门造车” 。
选择建立我们自己的
【弃用 Nginx,他们选择这款工具!】在过去的几年里,随着我们的客户群和功能集的持续增长,我们持续评估了三种选择:


推荐阅读