HTTP/2 协议深度解析
1. 二进制分帧层 (Binary Framing Layer)
HTTP/2 将 HTTP 消息分解为帧 (Frame),是协议的最小传输单位。
帧结构 (9 字节头 + Payload)
+-----------------------------------------------+
| Length (24) |
+---------------+---------------+---------------+
| Type (8) | Flags (8) |
+-+-------------+---------------+-------------------------------+
|R| Stream Identifier (31) |
+=+=============================================================+
| Frame Payload (0...) ...
+---------------------------------------------------------------+- Length: Payload 长度 (最大 16KB,可配置到 16MB)
- Type: 帧类型
- Flags: 标志位 (如 END_STREAM, END_HEADERS)
- Stream ID: 流标识符 (0 表示连接级别)
常见帧类型
| Type | 名称 | 用途 |
|---|---|---|
| 0x0 | DATA | 传输 HTTP Body |
| 0x1 | HEADERS | 传输 HTTP Headers (使用 HPACK 压缩) |
| 0x2 | PRIORITY | 流优先级 (已废弃,HTTP/3 移除) |
| 0x3 | RST_STREAM | 终止流 |
| 0x4 | SETTINGS | 配置参数 (如最大并发流数) |
| 0x5 | PUSH_PROMISE | 服务器推送 |
| 0x6 | PING | 心跳 / RTT 测量 |
| 0x7 | GOAWAY | 优雅关闭连接 |
| 0x8 | WINDOW_UPDATE | 流量控制 |
2. 流 (Stream) 与多路复用
Stream 是什么?
- 一个 逻辑上的双向字节流
- 每个 HTTP 请求/响应是一个 Stream
- 多个 Stream 在同一个 TCP 连接上并发传输
Stream 生命周期
+--------+
send PP | | recv PP
,--------| idle |--------.
/ | | \
v +--------+ v
+----------+ | +----------+
| | | send H / | |
,------| reserved | | recv H | reserved |------.
| | (local) | | | (remote) | |
| +----------+ v +----------+ |
| | +--------+ | |
| | recv ES | | send ES | |
| send H | ,-------| open |-------. | recv H |
| | / | | \ | |
| v v +--------+ v v |
| +----------+ | +----------+ |
| | half | | | half | |
| | closed | | send R / | closed | |
| | (remote) | | recv R | (local) | |
| +----------+ | +----------+ |
| | | | |
| | send ES / | recv ES / | |
| | send R / v send R / | |
| | recv R +--------+ recv R | |
| send R / `----------->| |<-----------' send R / |
| recv R | closed | recv R |
`----------------------->| |<-----------------------'
+--------+多路复用优势
- 消除队头阻塞 (HOL Blocking): 应用层面
- 减少连接数: 单连接处理所有请求
- Header 压缩: HPACK 算法
3. HPACK 头部压缩
核心思想
- 静态表: 预定义 61 个常见 Header (如
:method: GET) - 动态表: 连接级缓存,存储已传输的 Header
- Huffman 编码: 压缩 Header 值
示例
首次请求: User-Agent: Mozilla/5.0... (完整传输,加入动态表) 后续请求: 只需传输索引号 (如 62)
4. 流量控制 (Flow Control)
- 基于 WINDOW_UPDATE 帧
- 每个 Stream 和整个连接都有独立的窗口
- 防止快速发送方压垮慢速接收方
5. HTTP/2 的局限 → HTTP/3
尽管解决了应用层队头阻塞,TCP 层队头阻塞仍然存在:
- 一个 TCP 包丢失,所有 Stream 都被阻塞
- 解决方案: HTTP/3 基于 UDP (QUIC)