HTTP/2 多路复用原理
HTTP/2 如何通过二进制帧实现多路复用
问题
HTTP/2 中,多路复用的原理是什么?
解答
什么是多路复用
HTTP/1.1 的请求-响应模型是串行的:一个消息必须完成后才能处理下一个。HTTP/2 则允许多个消息在同一个连接上交织传输,这就是多路复用——在一个 TCP 连接上同时处理多个 HTTP 请求和响应。
HTTP/1.1 的局限
HTTP/1.1 基于文本协议,使用换行符分割 header 字段:
GET /index.html HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
这种解析方式存在问题:
串行处理:服务端需要不断读取字节直到遇到分隔符(\n 或 \r\n),在完成解析前无法处理其他请求。
内存不可控:无法预知一行内容的长度,服务端不知道该分配多大的缓冲区,既要保证性能又要避免内存浪费。
HTTP/2 的帧结构
HTTP/2 采用二进制帧设计,每个帧的前 9 个字节是固定格式:
+-----------------------------------------------+
| Length (24) |
+---------------+---------------+---------------+
| Type (8) | Flags (8) |
+-+-------------+---------------+-------------------------------+
|R| Stream ID (31) |
+=+=============================================================+
| Frame Payload (0...) ...
+---------------------------------------------------------------+
- Length (3 字节):帧负载的长度
- Type (1 字节):帧类型(HTTP/2 定义了 10 种帧类型)
- Flags (1 字节):帧标志位
- Stream ID (4 字节):流标识符,用于区分不同的请求/响应
多路复用的实现
服务端解析 HTTP/2 数据时,只需读取前 9 个字节就能知道:
- 这个帧属于哪个流(Stream ID)
- 帧的类型和长度
- 需要读取多少字节来完成这个帧
因为帧长度是已知的,服务端可以:
- 读取部分帧后切换处理其他流的帧
- 多个请求和响应的帧可以交错传输
- 在同一个 TCP 连接上并发处理多个 HTTP 消息
流(Stream) 是 HTTP/2 连接上独立的双向帧序列。同一个流的帧通过 Stream ID 关联,不同流的帧可以乱序发送,接收端根据 Stream ID 重组完整的请求或响应。
例如,客户端可以同时发送:
- Stream 1 的 HEADERS 帧
- Stream 3 的 DATA 帧
- Stream 1 的 DATA 帧
- Stream 5 的 HEADERS 帧
服务端根据 Stream ID 将这些帧分配到对应的流中处理。
关键点
- HTTP/2 使用二进制帧替代 HTTP/1.1 的文本格式,帧头固定 9 字节包含长度和流 ID
- 帧长度可预知,服务端可以灵活调度,无需等待完整消息即可切换处理其他流
- 流(Stream)通过 Stream ID 标识,同一连接上的多个流可以并发传输
- 多路复用消除了 HTTP/1.1 的队头阻塞问题,提升了连接利用率
目录