知识卡片

HTTP/2多路复用终结队首阻塞与连接数优化战争

结构图卡

内容

[[HTTP与TCP传输特征错配催生的前端优化Tricks及历史局限]]里”扩大并发连接数” 这条优化,源于HTTP/1.x的持久连接(Keep-Alive)虽然省去了重复建连的成本, 却带来”队首阻塞”问题:多个资源排在同一个TCP连接的FIFO队列里,若队首的 请求耗时很长,后面的资源即使服务端已并行算完,也无法插队返回——因为只 用一个连接传输多个资源,数据一旦交叉传输,客户端就分不清哪个包属于哪个 资源。HTTP/2用”帧”(Frame)取代”请求”作为最小传输单位彻底解决这个问题: 每个帧都带一个流ID标明自己属于哪个逻辑”流”(Stream),同一个TCP连接里 不同流的帧可以任意穿插传输,客户端凭流ID轻松重组出完整的请求/响应—— 这就是HTTP/2多路复用。有了它,每个域名只需要维持一个TCP连接(One Connection Per Origin),域名分片、合并雪碧图这类”用Tricks换并发”的 手段全部失去意义,甚至因为破坏HTTP/2基于字典编码的Header压缩效果(同一 连接上产生的请求越多,字典积累越全、压缩效果越好)而变成反模式。但多路 复用没有解决大文件传输问题——一个TCP包错误仍会导致所有流等待重传,这 是[[QUIC放弃TCP自建可靠传输的两大收益]]要解决的下一个问题。

结构图

flowchart TD
    A[HTTP/1.x: 请求是最小传输单位] -->|同一连接内请求排队FIFO| B[队首阻塞: 前面耗时请求堵住后面]
    B -->|Tricks: 域名分片/合并资源| C[副作用: 缓存失效/DNS负担/压缩变差]
    D[HTTP/2: 帧Frame是最小传输单位] -->|每帧携带流ID| E[同连接内不同流的帧可任意穿插]
    E --> F[客户端按流ID重组请求响应]
    F --> G[单域名单连接 One Connection Per Origin]

参考来源

- 位置:《凤凰架构:构建可靠的大型分布式系统》第4章"透明多级分流系统" 4.3.1节"连接数优化"(源文件:_epub-src对应OEBPS/Text/chapter41.xhtml) - 结论依据:原文详述队首阻塞的成因、HTTP/2用帧和流ID实现多路复用的 机制,并说明合并资源、域名分片在HTTP/2下反而破坏Header压缩效果、成为 反模式,直接支撑本卡片结构梳理。 - 原始内容:在HTTP/2中,帧(Frame)才是最小粒度的信息单位……每个帧都 附带一个流ID以标识这个帧属于哪个流。这样,在同一个TCP连接中传输的 多个数据帧就可以根据流ID轻易区分开来……有了多路复用的支持,HTTP/2 就可以对每个域名只维持一个TCP连接。