这是《计算机网络 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 HTTP/2 解决 HTTP/1.1 的连接效率问题:请求队头阻塞、头部重复、文本解析成本和难以并行。它通过二进制分帧、流多路复用、HPACK 头部压缩和单个 TCP 连接复用,显著提升高延迟链路和多请求页面的加载性能。
16.1 HTTP/1.1 的问题
HTTP/1.1 常见优化:
1. 浏览器对同一域名开启多个并发连接
2. 静态资源分到多个域名
3. Sprite、内联资源
4. 减少请求次数
原因:
- 同一连接上响应必须按请求顺序返回;
- 前一个慢响应会阻塞后续响应;
- 头部大量重复;
- 文本解析成本高;
- 多连接带来更多握手和拥塞竞争。
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 压缩头部:
- 静态表保存常见头部;
- 动态表保存连接内重复头部;
- 使用 Huffman 编码减少体积;
- 头部字段通过索引引用。
注意:
- 动态表依赖连接状态;
- 头部大小需限制,防止内存攻击;
- 敏感头部可标记
never indexed; - 压缩对高重复请求收益明显。
16.5 流优先级与依赖
HTTP/2 早期通过流依赖和权重表达优先级,实践中浏览器策略差异较大,后续标准演进引入了更简单的优先级信号。
工程目标:
- 关键 HTML 和 CSS 先传输;
- 首屏图片优先;
- 大文件不阻塞关键请求;
- 服务端可根据资源类型和业务重要性调度。
优先级只是建议,网络、服务器实现和调度策略都会影响最终顺序。
16.6 流量控制
HTTP/2 有连接级和流级窗口:
WINDOW_UPDATE
作用:
- 避免高速流淹没接收方;
- 控制单个流占用缓冲;
- 支持流级别的背压。
问题:
- 窗口过小限制吞吐;
- 应用读取慢会阻塞流;
- 代理转发慢会放大延迟;
- 高吞吐服务需评估缓冲策略。
16.7 服务端推送
服务端推送允许服务器主动发送预测资源,但实践中存在以下问题:
- 客户端缓存判断困难;
- 推送资源可能不需要;
- 占用关键带宽;
- 浏览器支持逐步弱化;
- 现代实现更倾向预加载提示。
不建议把服务端推送作为核心性能方案。
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,排查时应关注流状态、流量控制、代理兼容和连接超时。
思考题
- HTTP/2 如何解决 HTTP/1.1 的请求队头阻塞?
- 为什么 HTTP/2 仍有 TCP 队头阻塞?
- HPACK 的动态表有什么作用?
- HTTP/2 流量控制和 TCP 滑动窗口有什么区别?
- 如何验证线上站点已经启用 HTTP/2?