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 个字节就能知道:

  1. 这个帧属于哪个流(Stream ID)
  2. 帧的类型和长度
  3. 需要读取多少字节来完成这个帧

因为帧长度是已知的,服务端可以:

  • 读取部分帧后切换处理其他流的帧
  • 多个请求和响应的帧可以交错传输
  • 在同一个 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 的队头阻塞问题,提升了连接利用率