HTTP/1.x 中的连接管理

253 阅读7分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天,点击查看活动详情

HTTP/1.x 中的连接管理

连接管理是 HTTP 中的一个关键主题:打开和维护连接在很大程度上会影响网站和 Web 应用程序的性能。在 HTTP/1.x 中,有几种模型:短期连接持久连接和 HTTP 流水线。

HTTP主要依靠TCP作为其传输协议,在客户端和服务器之间提供连接。在起步阶段,HTTP使用单个模型来处理此类连接。这些连接是短暂的:每次需要发送请求时都会创建一个新连接,并在收到答案后关闭。

这个简单的模型对性能有固有的限制:打开每个TCP连接都是一个消耗资源的操作。必须在客户端和服务器之间交换几条消息。当请求需要发送时,网络延迟和带宽会影响性能。现代网页需要许多请求(十几个或更多)来提供所需的信息量,这证明这种早期模型效率低下。

在 HTTP/1.1 中创建了两个较新的模型。持久连接模型使连续请求之间的连接保持打开状态,从而减少了打开新连接所需的时间。HTTP流水线模型更进一步,发送多个连续的请求,甚至不等待答案,从而减少了网络中的大部分延迟。

比较三种 HTTP/1.x 连接模型的性能:短期连接、持久连接和 HTTP 流水线。

注意: HTTP/2 添加了用于连接管理的其他模型。

需要注意的是,HTTP 中的连接管理适用于两个连续节点之间的连接,即逐跳而不是端到端。客户端与其第一个代理之间的连接中使用的模型可能与代理和目标服务器(或任何中间代理)之间的模型不同。定义连接模型时涉及的 HTTP 标头(如 Connection 和 Keep-Alive)是逐跳标头,其值可由中间节点更改。

一个相关的主题是HTTP连接升级的概念,其中HTTP / 1.1连接升级到不同的协议,例如TLS / 1.0,WebSocket,甚至是明文中的HTTP / 2。此协议升级机制在别处有更详细的说明。

短期连接

HTTP 的原始模型和 HTTP/1.0 中的默认模型是短期连接。每个HTTP请求都在自己的连接上完成;这意味着在每个HTTP请求之前都会发生TCP握手,并且这些握手是序列化的。

TCP 握手本身非常耗时,但 TCP 连接会适应其负载,通过更持久(或更热)的连接变得更加高效。短期连接不利用 TCP 的此效率功能,并且通过持久的通过新的冷连接进行传输,性能从最佳状态下降。

此模型是 HTTP/1.0 中使用的默认模型(如果没有连接标头,或者其值设置为 )。在 HTTP/1.1 中,仅当发送值为 的连接标头时,才使用此模型。close``close

注意: 除非处理一个非常旧的系统,它不支持持久连接,否则没有令人信服的理由来使用这个模型。

持久连接

短期连接有两个主要障碍:建立新连接所需的时间很长,并且只有当此连接已使用一段时间(热连接)时,基础 TCP 连接的性能才会更好。为了缓解这些问题,甚至在HTTP / 1.1之前,就已经设计了持久连接的概念。或者,这可以称为保持活动状态连接

持久连接是一段时间内保持打开状态的连接,可以重用于多个请求,从而节省了对新 TCP 握手的需求,并利用了 TCP 的性能增强功能。此连接不会永远保持打开状态:空闲连接会在一段时间后关闭(服务器可以使用 Keep-Alive 标头来指定连接应保持打开状态的最短时间)。

持久连接也有缺点;即使在空闲时,它们也会消耗服务器资源,并且在负载过重的情况下,也可以进行DoS攻击。在这种情况下,使用非持久连接(这些连接在空闲时立即关闭)可以提供更好的性能。

默认情况下,HTTP/1.0 连接不是持久的。通常,将“连接”设置为 “以外的任何连接”都会使它们持久化。close``retry-after

在 HTTP/1.1 中,持久性是默认设置,不再需要标头(但它通常作为防御措施添加,以防需要回退到 HTTP/1.0 的情况)。

HTTP 流水线

注意: 默认情况下,在现代浏览器中不会激活 HTTP 流水线:

  • Buggy代理仍然很常见,这些代理会导致Web开发人员无法轻松预见和诊断的奇怪和不稳定的行为。
  • 正确实现流水线很复杂:正在传输的资源的大小,将使用的有效RTT以及有效带宽,对管道提供的改进有直接影响。如果不知道这些,重要消息可能会被延迟到不重要的消息后面。重要的概念甚至在页面布局过程中不断发展!因此,HTTP流水线在大多数情况下只带来了边际改进。
  • 流水线受霍尔问题的影响。

由于这些原因,流水线已被HTTP / 2使用的更好的算法多路复用所取代。

默认情况下,HTTP 请求是按顺序发出的。只有在收到对当前请求的响应后,才会发出下一个请求。由于它们受网络延迟和带宽限制的影响,因此在服务器看到下一个请求之前,这可能会导致明显的延迟。

流水线是在同一个持久连接上发送连续请求的过程,而无需等待答案。这样可以避免连接的延迟。从理论上讲,如果将两个HTTP请求打包到同一个TCP消息中,也可以提高性能。典型的 MSS(最大段大小)足够大,可以包含几个简单的请求,尽管 HTTP 请求的大小需求持续增长。

并非所有类型的 HTTP 请求都可以流水线化:只有幂等方法(即 GETHEADPUT 和 DELETE)可以安全地重放。如果发生故障,可以重复管道内容。

今天,每个符合HTTP / 1.1标准的代理和服务器都应该支持流水线,尽管许多代理和服务器在实践中都有局限性:这是默认情况下没有现代浏览器激活此功能的重要原因。

域分片

注意: 除非您有非常具体的直接需求,否则不要使用此已弃用的技术;改为 HTTP/2。在HTTP / 2中,域分片不再有用:HTTP / 2连接能够很好地处理并行的未优先请求。域分片甚至对性能有害。大多数 HTTP/2 实现使用一种称为连接合并的技术来恢复最终的域分片。

由于 HTTP/1.x 连接正在序列化请求,因此即使没有任何排序,如果没有足够大的可用带宽,它也无法成为最佳连接。作为一种解决方案,浏览器打开到每个域的多个连接,并发送并行请求。默认值曾经是 2 到 3 个连接,但现在这已增加到更常见的 6 个并行连接。如果尝试的次数超过此数字,则存在触发服务器端 DoS 保护的风险。

如果服务器希望更快的网站或应用程序响应,则服务器可以强制打开更多连接。例如,与其将所有资源放在同一个域上,不如说,它可以拆分为多个域,, , 。这些域中的每一个都解析为一个服务器,Web浏览器将为每个域打开6个连接(在我们的示例中,将连接提升到18个)。这种技术称为域分片www.example.com``www1.example.com``www2.example.com``www3.example.com

结论

改进的连接管理可以显著提高 HTTP 的性能。使用 HTTP/1.1 或 HTTP/1.0,使用持久连接(至少在它变为空闲之前)可以获得最佳性能。但是,流水线的失败导致了设计出卓越的连接管理模型,这些模型已被合并到HTTP / 2中。