[博客翻译]HTTP/2在负载均衡器之后没有多大意义


原文地址:https://byroot.github.io/ruby/performance/2025/02/24/http2-past-the-load-balancer.html


超出负载均衡器后,HTTP/2 的意义不大

我想写一篇关于 Pitchfork 的文章,解释它的起源、为什么它目前是这样的,以及我对它未来的一些看法。但在深入讨论之前,我觉得需要先分享一下我对某些技术主题的看法——这次的主题是 HTTP/2。

无论是在线还是在技术会议上,我偶尔会听到人们对 Ruby HTTP 服务器(比如 Puma)不支持 HTTP/2 表示不满。每当遇到这种情况时,我都会问他们为什么要这个功能。但到目前为止,还没有人能提供一个实际的使用场景。

对我来说,这种缺乏支持并不是什么大问题,因为我唯一能想到的情况就是,有人希望直接将 Ruby 应用程序暴露在互联网上,而不通过任何负载均衡器或反向代理。虽然这样看起来可以“少了一层架构”,但从我的经验来看,这其实并不值得这么做。

如果你对 HTTP 协议不太熟悉,也不知道 HTTP/2 和 HTTP/3 有什么区别,你可能会觉得我的观点有些奇怪。所以下面我会尽量用通俗易懂的语言来解释 HTTP/2 到底解决了哪些问题,以及为什么在内部网络中它可能并不重要。

HTTP/2 解决了什么问题?

HTTP/2 的雏形最早是在 2009 年以 SPDY 的形式出现的,主要目标是减少页面加载延迟,使网页加载更快。在当时的互联网中,网页不再只是一个简单的 HTML 文件,而是由许多资源组成的集合,包括样式表、脚本和图片等。因此,当浏览器下载并解析主页面后,还需要下载这些额外的资源。

在 2000 年代后期,随着网页内容变得越来越复杂,所需的资源数量也在不断增加。尽管宽带的速度在提升,但这并不能完全弥补 HTTP/1.1 在处理大量小文件时效率低下的问题。其中一个主要原因在于,根据 RFC 2616 标准(定义了 HTTP/1.1),浏览器只能与同一域名建立两个并发连接:

客户端在使用持久连接时,应限制其与给定服务器保持的并发连接数。单用户客户端不应同时维持超过两个连接到任何一个服务器或代理。

这意味着即使你的网络带宽很大,如果每个请求都需要等待前一个请求完成,那么加载几十个小资源将会变得非常慢。举个例子,假设你需要通过跨大西洋的服务器加载 100 个小型资源,而你的 ping 值大约为 60 毫秒。如果你只用了两个并发连接,整个加载时间至少为 ping * (资源数 / 连接数),也就是约 3 秒,这是很糟糕的体验。

正因为如此,在那时像“资源打包”(assets bundling)这样的前端优化技术变得非常重要。它们通过合并多个文件,减少了请求次数,从而显著提升了页面加载速度[1]。还有些网站采用了“域名分片”(domain sharding)技术,将资源分散到不同的域名下,以增加并发能力。

理论上,HTTP/1.1 有一个叫做“请求管道化”的功能,允许在一个连接上连续发送多个请求而无需等待前一个响应。但实际上,由于一些服务器的行为不当,大多数浏览器最终禁用了这一功能。即使没有被禁用,该功能也有一个问题:队首阻塞(Head-of-Line Blocking)。即如果某个资源的生成速度较慢,则后续所有资源都无法发送。

为了缓解这些问题,到了 2008 年,大部分浏览器开始突破原有的两个连接限制,Firefox 3 将每域名的最大连接数提高到 6,其他浏览器也很快跟进。然而,增加并发连接并非完美解决方案,因为每个 TCP 连接都有一个“慢启动”阶段。当建立新的连接时,计算机不知道这条链路的极限吞吐量是多少,因此初始速度较慢,逐渐加速,直到收到丢包通知为止。这就是为什么持久连接如此重要——已经使用的连接比新建立的连接具有更高的吞吐量。

HTTP/2 正是通过允许多路复用(multiplexing)来解决这些问题,它可以让多个请求共享同一个 TCP 连接,避免了队首阻塞[2]。除此之外,HTTP/2 还引入了一些其他特性,比如强制使用加密[3]、压缩头部信息(用 GZip)以及“服务器推送”(server push),但其中最重要的还是多路复用。


为什么局域网中 HTTP/2 不重要?

HTTP/2 的核心优势在于多路复用,尤其在网络环境较差的情况下(例如移动互联网),它可以带来显著性能提升。但在数据中心环境中却未必如此。

仔细想想,在我们上面提到的计算中,影响最大的因素是往返时间(RTT,即“ping”值)。除非你的基础设施设计得非常差,否则服务器(例如 Puma)与其客户端(负载均衡器或反向代理)之间的往返时间通常非常短,通常不到一毫秒,远远小于实际处理请求所需的时间。换句话说,在局域网中,HTTP/2 多路复用的优势几乎无法体现出来。

另外,局域网中的连接往往会长时间存在,因此基本