一个页面要取很多资源,每个资源都新建一条 TCP 连接太贵,所以有了持久连接和(曾经的)流水线。这篇在 100 ms 往返的链路上量:复用连接省了多少个往返、流水线又省了多少、它为什么没有被普遍使用——顺便抓到了一次真实的 Nagle 算法拖慢。
每次新建连接:10 个资源总共 2024 ms(≈ 10 × (握手 1 个 RTT + 请求响应 1 个 RTT) = 10 × 200 ms) 同一条连接上依次取:总共 1114 ms(≈ 握手 1 RTT + 10 × 1 RTT = 11 × 100 ms) 省下 910 ms,约 9.1 个 RTT;每个资源平均 202 ms 对 111 ms
每次新建要 2 个 RTT,keep-alive 只要 1 个。10 个资源省下约 9 个 RTT。
流水线:10 个资源总共 233 ms(握手 1 RTT + 一次请求响应 1 RTT ≈ 200 ms);第 1 个响应在握手后 100 ms,第 10 个在 133 ms 对比:非流水线的 keep-alive 1114 ms;每次新建 2024 ms
不等响应连续发请求,10 个资源总共约 2 个 RTT。
同一条连接流水线(第 1 个慢),服务器默认(Nagle 开):5 个响应到达时刻(从握手完成起,ms):[702, 802, 802, 802, 802] 同一条连接流水线(第 1 个慢),服务器 TCP_NODELAY:[704, 704, 704, 704, 704] 5 条并行连接(含握手):到达时刻 [806, 202, 202, 202, 202] 快请求在流水线里被拖到 704 ms(NODELAY)之后,在并行连接里 202~202 ms 就拿到了;Nagle 开时后 4 个比第 1 个晚了 100 ms,NODELAY 时晚了 0 ms
响应必须按请求顺序返回,第一个慢,后面的都得等;并行连接则互不影响。服务端不开 TCP_NODELAY 还会再慢一个 RTT。
3 个请求一次发出,3 秒内收到 2799 字节,其中 "HTTP/1.1 200 OK" 状态行 3 个;状态行们:[b'HTTP/1.1 200 OK', b'HTTP/1.1 200 OK', b'HTTP/1.1 200 OK']
example.com 能处理一次发出的 3 个流水线请求。
响应头里和连接有关的:Connection = keep-alive,Keep-Alive = None 130 秒内服务器一直没有关闭连接
example.com 的持久连接空闲 130 秒仍未被关闭。