进入最后的演进与排障阶段。前面 25 篇大部分在讲 HTTP/1.1(毕竟它是基础,而且至今仍占很大比例)。但 HTTP/1.1 有两个结构性瓶颈——队头阻塞和文本格式——HTTP/2 就是为解决它们而生的。
这一篇讲 HTTP/2 最核心的改造:多路复用。
HTTP/2 的三个根本变化
HTTP/2(RFC 9113,2015 年)相对 HTTP/1.1 有三个根本性变化:
- 文本变二进制:HTTP/1.1 是文本协议(报文是可读文本),HTTP/2 把报文拆成二进制帧。解析更快、更紧凑,但失去了「肉眼看报文」的可读性。
- 一条连接跑多个请求(多路复用):HTTP/1.1 一条连接只能串行跑一个请求,HTTP/2 一条连接能并发跑无数个请求。
- 头部压缩(HPACK):HTTP/1.1 每个请求都重复发一堆 header(User-Agent、Cookie 等),HTTP/2 用 HPACK 压缩头部,省大量冗余。
这篇聚焦第 2 点(多路复用),第 3 点(头部压缩)下一篇详讲。
多路复用:一条连接,多个 stream
HTTP/1.1 的痛点是:一条 TCP 连接上请求必须串行,前一个慢响应阻塞后面所有请求(应用层队头阻塞)。浏览器的应对是开多条连接(6 个),但每条内部还是串行。
HTTP/2 的解法是把「请求」抽象成 stream(流)。一条 TCP 连接上可以有无数个 stream,每个 stream 承载一个请求-响应,stream 之间相互独立、可以并发。
在 HTTP/2 里,数据被拆成二进制帧(frame),每个帧标记它属于哪个 stream(用 stream id)。发送方把多个 stream 的帧交错着发到同一条 TCP 连接上,接收方按 stream id 把帧重新组装成各自的响应。
效果是:30 个请求不再需要开 30 条连接(或挤在 6 条里串行),而是在一条连接上 30 个 stream 并发跑。响应也不用按顺序——stream A 的帧和 stream B 的帧交错传输,谁好了谁先回,不存在「慢响应阻塞快响应」。
这就彻底解决了应用层队头阻塞——第 8 篇讲的 HTTP/1.1 那个最深的坑。
帧是 HTTP/2 的基本单位
理解 HTTP/2 要先理解「帧(frame)」。HTTP/2 把每个请求-响应拆成多个帧:
- HEADERS 帧:承载请求/响应的 header(经过 HPACK 压缩)。
- DATA 帧:承载 body。
- 还有 SETTINGS、PING、WINDOW_UPDATE 等控制帧。
每个帧有个 stream id,表示它属于哪个 stream。一条连接上所有 stream 的帧混在一起传输,接收方按 stream id 分拣。这就是「多路复用」的底层机制——帧是共享的传输单元,stream 是逻辑上的请求-响应通道。
服务器推送(Server Push)
HTTP/2 还有个特性:服务器推送。客户端请求 /index.html,服务器知道你接下来一定会要 /style.css 和 /app.js,于是不等客户端请求,主动把这两个资源推过来。
理论上这能省往返。但实践中 Server Push 用得很少——因为服务器很难准确预测客户端要不要某个资源(可能客户端已经缓存了),推送错了反而浪费带宽。Chrome 后来甚至移除了对 Server Push 的支持。这是个「理论美好、实践拉胯」的特性。
那个悖论:填了应用层 HOL,放大了 TCP 层 HOL
第 8 篇讲过,HTTP/2 解决了应用层队头阻塞,但带来了一个悖论:它反而放大了 TCP 层队头阻塞。
因为 HTTP/2 把所有请求挤到一条连接上(多路复用),这条连接一旦丢包,TCP 的有序交付机制会让整条连接上所有 stream 都卡住等重传。HTTP/1.1 时代,丢包只影响一条连接(一个请求);HTTP/2 时代,丢包影响这条连接上所有请求。
这个悖论是 HTTP/3 要彻底换掉 TCP 的根本原因——HTTP/3 用基于 UDP 的 QUIC,每个 stream 独立,丢包只卡那个 stream,不连累别的。
取舍与边界
HTTP/2 有几个值得注意的边界:
- HTTP/2 基本只用在 HTTPS 上。虽然协议层 HTTP/2 不强制加密,但所有主流浏览器都只在 HTTPS(h2)上支持 HTTP/2,明文 HTTP/2(h2c)浏览器不支持。所以上 HTTP/2 的前提是上 HTTPS。
- HTTP/2 向后兼容 HTTP/1.1 的语义。method、status、header 这些语义层完全一样,HTTP/2 改的是传输层(怎么打包发送),不改语义层。所以你的 API、你的 header 逻辑不用改。
- 升级机制。客户端和服务器先在 HTTPS 握手时通过 ALPN 协商「用 h2 还是 http/1.1」,双方都支持就用 HTTP/2,否则降级。
收束:HTTP/2 是传输层的重构
HTTP/2 没动 HTTP 的语义(method/status/header 还是一样),它重做的是传输层:文本变二进制、串行变并发(多路复用)、冗余变压缩(HPACK)。它填了 HTTP/1.1 应用层队头阻塞的坑,但因为还跑在 TCP 上,TCP 层队头阻塞反而被放大——这是 HTTP/3 的动机。
下一篇讲 HPACK——HTTP/2 怎么压缩头部,为什么同一个 header 在多个请求间不用重复发。
关于十三Tech
我是十三,All in AI Agent 方向的架构师,专注 AI 工程实践。
我相信 AI 是程序员的最佳搭档,也希望帮助每一位开发者更好地驾驭 AI。
如果你想继续跟完这套「图解 HTTP」,欢迎关注公众号 「十三Tech」。后续会按 URL 与报文、连接与传输、缓存与协商、安全与边界、HTTP/2 与 HTTP/3 这条线更新。

