HTTP/2 多路复用原理
HTTP/2 如何通过二进制帧实现多路复用
问题
HTTP/2 中,多路复用的原理是什么?
解答
什么是多路复用
HTTP/1.1 的请求-响应模型是串行的:一个 HTTP 消息必须完成后,才能处理下一个。而 HTTP/2 允许多个消息在同一个连接上交织传输,这就是多路复用——在一个 TCP 连接上,多个 HTTP 消息同时工作。
HTTP/1.1 为什么不能多路复用
HTTP/1.1 是基于文本分割解析的协议。请求消息格式如下:
GET /index.html HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
服务端需要不断读入字节,直到遇到换行符(\n 或 \r\n)才能解析一行。这种方式存在两个问题:
- 一次只能处理一个请求或响应,在完成之前不能停止解析
- 无法预知需要多少内存,不知道该分配多大的缓冲区
HTTP/2 的帧结构
HTTP/2 是基于二进制帧的协议。帧是数据的基本单元,结构如下:
+-----------------------------------------------+
| Length (24) |
+---------------+---------------+---------------+
| Type (8) | Flags (8) |
+-+-------------+---------------+-------------------------------+
|R| Stream Identifier (31) |
+=+=============================================================+
| Frame Payload (0...) ...
+---------------------------------------------------------------+
前 9 个字节对每个帧都是固定的:
- Length (3 字节):帧负载的长度
- Type (1 字节):帧类型
- Flags (1 字节):标志位
- Stream Identifier (4 字节):流 ID
服务器只需解析前 9 个字节,就能准确知道整个帧的大小,一切可预知、可控。
多路复用的实现
HTTP/2 引入了”流”的概念:连接上独立的、双向的帧序列交换。每个帧的 Stream ID 标识它属于哪个流。
多个请求和响应可以通过不同的 Stream ID 在同一个连接上交错传输:
- 请求 A 的 HEADERS 帧(Stream ID: 1)
- 请求 B 的 HEADERS 帧(Stream ID: 3)
- 请求 A 的 DATA 帧(Stream ID: 1)
- 响应 B 的 HEADERS 帧(Stream ID: 3)
- 请求 A 的 DATA 帧(Stream ID: 1)
- 响应 A 的 HEADERS 帧(Stream ID: 1)
这样就实现了多个 HTTP 消息在同一连接上的并发传输。
关键点
- HTTP/2 使用二进制帧而非文本格式,帧头固定 9 字节,长度可预知
- 每个帧通过 Stream ID 标识所属的流,不同流的帧可以交错传输
- HTTP/1.1 基于文本分割解析,必须串行处理,无法实现多路复用
- 多路复用提高了连接利用率,多个请求响应可以在一个 TCP 连接上并发
目录