Computer NetworkNotes

第 16 章:HTTP/2

zjc 于 2026-01-16 发布

这是《计算机网络 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 HTTP/2 解决 HTTP/1.1 的连接效率问题:请求队头阻塞、头部重复、文本解析成本和难以并行。它通过二进制分帧、流多路复用、HPACK 头部压缩和单个 TCP 连接复用,显著提升高延迟链路和多请求页面的加载性能。

16.1 HTTP/1.1 的问题

HTTP/1.1 常见优化:

1. 浏览器对同一域名开启多个并发连接
2. 静态资源分到多个域名
3. Sprite、内联资源
4. 减少请求次数

原因:

  1. 同一连接上响应必须按请求顺序返回;
  2. 前一个慢响应会阻塞后续响应;
  3. 头部大量重复;
  4. 文本解析成本高;
  5. 多连接带来更多握手和拥塞竞争。

16.2 二进制分帧

HTTP/2 将消息拆成帧:

| Length | Type | Flags | Stream Identifier | Frame Payload |

常见帧:

作用
HEADERS 请求或响应头
DATA 请求或响应体
SETTINGS 连接参数
WINDOW_UPDATE 流量控制
PRIORITY 优先级,后续演进中作用弱化
RST_STREAM 取消流
PING 连接保活与 RTT 测量
GOAWAY 优雅关闭连接

一个请求或响应是一个流,流由多个帧组成。

16.3 多路复用

TCP Connection
  |-- Stream 1:GET /api/user
  |-- Stream 3:GET /api/orders
  |-- Stream 5:POST /api/payment
  +-- Stream 7:GET /static/app.js

多个流共享一条连接,帧可以交错传输。高 RTT 网络中,不必为每个资源重新建连,也不必等待浏览器连接池分配。

多路复用不能突破 TCP 单字节流限制:

HTTP/2 消除应用层请求队头阻塞
但 TCP 任何一个包丢失会阻塞所有流的字节交付

这是 HTTP/3 和 QUIC 的重要动机。

16.4 HPACK

HPACK 压缩头部:

  1. 静态表保存常见头部;
  2. 动态表保存连接内重复头部;
  3. 使用 Huffman 编码减少体积;
  4. 头部字段通过索引引用。

注意:

  1. 动态表依赖连接状态;
  2. 头部大小需限制,防止内存攻击;
  3. 敏感头部可标记 never indexed
  4. 压缩对高重复请求收益明显。

16.5 流优先级与依赖

HTTP/2 早期通过流依赖和权重表达优先级,实践中浏览器策略差异较大,后续标准演进引入了更简单的优先级信号。

工程目标:

  1. 关键 HTML 和 CSS 先传输;
  2. 首屏图片优先;
  3. 大文件不阻塞关键请求;
  4. 服务端可根据资源类型和业务重要性调度。

优先级只是建议,网络、服务器实现和调度策略都会影响最终顺序。

16.6 流量控制

HTTP/2 有连接级和流级窗口:

WINDOW_UPDATE

作用:

  1. 避免高速流淹没接收方;
  2. 控制单个流占用缓冲;
  3. 支持流级别的背压。

问题:

  1. 窗口过小限制吞吐;
  2. 应用读取慢会阻塞流;
  3. 代理转发慢会放大延迟;
  4. 高吞吐服务需评估缓冲策略。

16.7 服务端推送

服务端推送允许服务器主动发送预测资源,但实践中存在以下问题:

  1. 客户端缓存判断困难;
  2. 推送资源可能不需要;
  3. 占用关键带宽;
  4. 浏览器支持逐步弱化;
  5. 现代实现更倾向预加载提示。

不建议把服务端推送作为核心性能方案。

16.8 部署与调试

启用条件:

HTTPS + ALPN h2

Nginx 新版本示例:

server {
    listen 443 ssl;
    http2 on;
    server_name www.example.com;
}

不同版本配置语法可能不同,旧版本可能使用 listen 443 ssl http2;

查看协议:

curl -I --http2 https://www.example.com
curl -v --http2 https://www.example.com
nghttp -v https://www.example.com

浏览器开发者工具的 Protocol 列也可以查看是否为 h2

16.9 常见问题

单连接竞争

大量下载共享一条 TCP 连接,可能影响关键小请求。可用限速、资源优化和 HTTP/3 缓解。

中间设备兼容

代理、LB、WAF 必须正确转发 HTTP/2,或明确终止后转为 HTTP/1.1。

头部过大

检查 HPACK、日志中间件和头部大小限制。

流重置

客户端取消页面请求会发送 RST_STREAM,需区分正常取消和异常崩溃。

连接突然关闭

观察 GOAWAY、空闲超时、TLS 错误和 LB 策略。

本章小结

HTTP/2 使用二进制分帧和流实现多路复用,用 HPACK 减少重复头部,用连接级和流级窗口实现流量控制。它降低了高延迟链路上的建连和排队成本,但仍受 TCP 队头阻塞影响。部署需 HTTPS 和 ALPN,排查时应关注流状态、流量控制、代理兼容和连接超时。

思考题

  1. HTTP/2 如何解决 HTTP/1.1 的请求队头阻塞?
  2. 为什么 HTTP/2 仍有 TCP 队头阻塞?
  3. HPACK 的动态表有什么作用?
  4. HTTP/2 流量控制和 TCP 滑动窗口有什么区别?
  5. 如何验证线上站点已经启用 HTTP/2?