HTTP权威指南 连接管理

《HTTP 权威指南》第四章——连接管理,阅读笔记。

TCP 延迟确认

由于 TCP 确认报文很小,所以 TCP 允许在发往相同方向的输出数据分组中对其进行“捎带”。延迟确认算法会在一个特定的窗口时间(通常是 100 ~ 200毫秒)内将输出确认存放在缓冲区中,以寻求能够捎带它的输出数据分组。如果在那个时间内没有输出数据分组,就将确认信息放在单独的分组中传送。由于 HTTP 协议的特点,可以调整或禁止延迟确认算法。

TCP 慢启动

TCP 连接会随着时间进行自我“调谐”,起初会限制连接的最大速度,如果数据成功传输,会随着时间的推移提高传输速度,这种调谐成为 TCP 慢自动(slow start),用于防止因特网的突然过载和拥塞。
TCP 慢启动限制了一个 TCP 端点在任意时刻可以传输的分组数。简单来说,没成功接收一个分组,发送端就有发送另外两个分组的权限,然后确认了这两个分组之后就可以发送四个分组。

Nagle算法与 TCP_NODELAY

每个 TCP 段中都至少装载了 40 个字节的标记和首部,所以如果 TCP 发送了大量包含少量数据的分组,网络的性能就会严重下降。Nagle 算法试图在发送一个分组之前,将大量 TCP 数据绑定在一起,以提高网络效率。
Nagle 算法鼓励发送全尺寸(LAN 上最大尺寸的分组大约 1500 字节,因特网上是几百字节)的段。只有当所有其他分组都被确认之后,Nagle 算法才允许发送非全尺寸的分组。如果其他分组仍然在传输过程中,就将那部分数据缓存起来。只有当挂起分组被确认,或者缓存中积累了足够发送一个全尺寸的数据时,才会将缓存的数据发送出去。
Nagle 算法引发以下几种 HTTP 性能问题:

  1. 小的 HTTP 报文可能无法填满一个分组,可能会因为等待那些永远不会到来的额外数据而产生时延;
  2. Nagle 算法与延迟确认之间的交互存在问题——Nagle 算法会阻止数据的发送,直到有确认分组抵达为止,但确认分组自身会被延迟确认算法延迟100 ~ 200 毫秒。

HTTP 应用程序通常会在自己的栈中设置参数 TCP_NODELAY 禁用 Nagle 算法,提高性能。

Connection 首部

Connection 首部定义了 HTTP 连接的一些信息,可以承载 3 种不同类型的标签:

  • HTTP 首部字段名,列出了只与此连接有关的首部;
  • 任意标签值,用于描述此连接的非标准选项;
  • 值close,说明操作完成之后需关闭这条持久连接;

如果连接标签中包含了一个 HTTP 首部字段的名称,那么这个首部字段就包含了与一些连接有关的信息,不能将其转发出去(对于中间代理和高速缓存等 HTTP 中间实体)。HTTP 应用程序收到一条带有 Connection 首部的报文时,接收端会解析发送端请求的所有选项,并将其应用。然后会在将此报文转发给下一跳地址之前,删除 Connection 首部以及 Connection 中列出的所有首部。而且,可能还会有少量没有作为 Connection 首部值列出,但一定不能被代理转发的逐跳首部,包括:Proxy-Authenticate、Proxy-Connection、Transfer-Encoding、Upgrade。

串行事务

最原始最简单的 HTTP 事务。

并行连接

同时打开多条连接来处理 HTTP 事务。这种方式只是看起来以及让人感觉起来页面加载速度快了,但是并不一定真的会快的。在机器性能较差以及网速较慢的环境,多条连接都会去竞争机器资源以及网络带宽,这会使得所有请求都很慢。

持久连接

站点本地性(site locality):一个 web 页面上的大部分引用资源都来自同一个 web 站点,并且初始化了某服务器 http 请求的应用程序很可能会在不久的将来对那台服务器发起更多的请求。
使用持久连接,就可以避免建立连接时延、慢启动时延。持久连接配合使用并行连接可能是最高效的方式。
持久连接有两种类型:

  • 比较老的 HTTP/1.0+ “keep-alive”
  • 现代的 HTTP/1.1 “persistent”

实现 HTTP/1.0 keep-alive 连接的客户端可以通过包含 Connection: Keep-Alive 首部请求将一条连接保持在打开状态。如果服务器愿意为下一条请求将连接保持在打开状态,就在响应中包含相同的首部。如果响应中没有 Connection: Keep-Alive 首部,客户端就认为服务器不支持 keep-alive,会在发回响应报文之后关闭连接。
不同于 HTTP/1.0+,HTTP/1.1 的持久连接默认情况下是激活的。

Keep-Alive 通用首部

Keep-Alive 通用首部中使用由逗号分隔的选项来调节 Keep-Alive 的行为:

  • timeout,指定了连接需要保持的时间,单位为秒
  • max,指定了连接还会为多少个事务服务

管道化连接

HTTP/1.1 允许在持久连接上可选地使用请求管道。这是在 keep-alive 连接上的进一步性能优化。在响应到达之前,可以将多条请求放入队列。当第一条请求通过网络流向地球另一端的服务器时,第二条和第三条请求也可以发送了。