多路复用(Multiplexing)
HTTP/2 的 多路复用(Multiplexing) 是其核心特性之一,通过在单个 TCP 连接上并行传输多个请求和响应,彻底解决了 HTTP/1.x 的队头阻塞问题。
1. HTTP/1.x 的队头阻塞问题
在 HTTP/1.1 中:
- 串行传输:请求必须按顺序发送,前一个请求未完成时,后续请求会被阻塞(即使带宽充足)。
- 连接数限制:浏览器对同一域名限制 6-8 个并发连接,高并发场景需排队。
- 管线化(Pipelining)的失败:
虽然允许一次性发送多个请求,但响应必须按顺序返回,一个慢响应会阻塞后续所有响应。
2. HTTP/2 多路复用的工作原理
(1)流(Stream)、消息(Message)与帧(Frame)
- 流(Stream):一个独立的双向通信通道,承载一个请求及其响应。每个流有唯一 ID 和优先级。
- 消息(Message):完整的请求或响应,由多个帧组成(如
HEADERS
帧 + 多个DATA
帧)。 - 帧(Frame):数据传输的最小单位,每个帧包含:
- 流 ID:标识所属的流。
- 类型:如
HEADERS
(头部)、DATA
(数据)、PRIORITY
(优先级)等。 - 负载:实际数据(如压缩后的头部或响应体)。
(2)帧的传输与重组
- 乱序发送:不同流的帧可以交错发送(例如:流 1 的
DATA
帧 → 流 3 的HEADERS
帧 → 流 1 的DATA
帧)。 - 按流 ID 重组:接收方根据帧中的流 ID 将分散的帧重新组装为完整的消息。
- 独立性:每个流的处理不受其他流影响,即使某个流的数据包丢失或延迟,其他流仍可继续传输。
(3)优先级与依赖关系
- 流优先级:客户端可为流分配权重(如 CSS 文件优先于图片),服务器据此优化资源发送顺序。
- 依赖树:流可声明依赖其他流(如 HTML 依赖 JS),确保关键资源优先加载。
3. 多路复用的实现优势
(1)消除应用层队头阻塞
- 并行传输:多个请求/响应可同时处理,无需等待前一个完成。
- 示例:
页面加载 10 张图片时,HTTP/1.1 需排队逐个下载,而 HTTP/2 可同时接收所有图片的帧。
(2)减少连接开销
- 单连接承载所有流量:无需创建多个 TCP 连接(HTTP/1.x 的 6-8 个连接),降低 TLS 握手、TCP 慢启动的消耗。
- 适应高延迟网络:尤其对移动端(如 4G/5G)性能提升显著。
(3)带宽利用率最大化
- 动态填充 TCP 窗口:多个流的数据混合发送,避免某个流短暂空闲导致的带宽浪费。
4. 多路复用与 HPACK 的协同
- 头部压缩减少帧体积:HPACK 将头部压缩为小体积帧,使多路复用的帧更密集,传输效率更高。
- 动态表共享:所有流共享同一动态表,复用已传输的头部字段,进一步减少冗余。
5. 多路复用的局限性
(1)TCP 层队头阻塞
- TCP 的可靠性限制:若某个 TCP 包丢失,后续所有流的帧需等待重传(即使它们本身未丢失)。
解决方案:HTTP/3 基于 QUIC 协议,改用 UDP 并实现流级别的可靠性。
(2)优先级实现的复杂性
- 服务器可能忽略客户端指定的优先级,或实现不一致(如 CDN 厂商策略差异)。
6. 性能对比示例
场景:加载包含 20 个资源的网页
- HTTP/1.1:
6 个并发连接,分 4 批下载(20/6 ≈ 4 轮),每轮受队头阻塞影响。 - HTTP/2:
单连接多路复用,所有资源几乎同时下载,仅受带宽和资源大小限制。
7. 总结
HTTP/2 的多路复用通过 流、帧、优先级 的协同设计,实现了:
- 更高的连接利用率
- 更低的延迟
- 更强的并发能力
它是 HTTP/2 性能飞跃的核心,但也需结合 HPACK 压缩和合理的流管理策略才能发挥最大效果。