迁移注意事项

哪些 1.1 知识作废、哪些照旧,以及升级 h2/h3 时真正会踩的坑。

作者 David更新于 第 16 篇(共 16 篇)

哪些 1.1 知识作废

从 HTTP/1.1 专栏带过来的内容里,**只有第 1 部分(报文与成帧)**在 h2/h3 上失效:

作废的替代
报文四段式结构、CRLF、obs-fold二进制帧
request-line / status-line伪头字段
七步成帧判定链帧长 + END_STREAM/FIN
Transfer-Encoding、chunked帧层负责
Connection、Keep-Alive、UpgradeALPN + SETTINGS + GOAWAY
流水线、逐跳字段概念流多路复用

哪些照旧

第 2、3 部分逐字有效,三版通用:

升级协议不改变任何业务语义。ETag 还是那个 ETag,Cache-Control 还是那套规则。

应用层几乎不用改

对绝大多数应用,升级 h2/h3 是纯运维动作——终结点(nginx / CDN / 网关)改配置即可,应用代码不动。因为:

  • 网关会自动完成 h2/h3 ↔ 1.1 的转换。
  • 框架(Express、Spring、Go net/http)对上层暴露的是同一套请求/响应对象。

需要改代码的少数情况见下。

真正会踩的坑

1. 字段名大小写

h2/h3 强制小写。若代码里有:

if (req.headers['Content-Type'] === ...)   // h2 下永远取不到

必须改为小写查找。多数框架已归一化,但自己拼原始头或用底层库时要注意。

2. 依赖 1.1 特有字段的逻辑

if (req.headers.connection === 'keep-alive')  // h2/h3 下该字段不存在
if (req.headers['transfer-encoding'])         // 同上

这些字段在 h2/h3 中被禁止出现,相关判断会静默失效。

3. 域名分片要撤掉

1.1 时代把静态资源拆到 img1.example.com、img2.example.com 以突破 6 连接限制。h2/h3 下这是负优化:每个域要单独握手、单独维护连接与压缩上下文。合并回单域。

同理,资源合并(雪碧图、打包成一个巨型 JS)的收益也大幅下降——多路复用后小文件不再昂贵,且细粒度更利于缓存命中。但也不必走极端拆成上千个小文件,请求本身仍有开销。

4. INITIAL_WINDOW_SIZE 默认值太小

h2 默认 65535 字节。跨洋 100ms RTT 下单流吞吐上限约 640 KB/s——大文件下载会明显变慢,且这个现象常被误判为「h2 比 1.1 慢」。

nginx 示例:

http2_body_preread_size    64k;

更关键的是上游代理与应用服务器的窗口设置,需逐层检查。

5. MAX_CONCURRENT_STREAMS 必须设有限值

规范默认无限。不设置等于对流洪泛不设防(含 Rapid Reset CVE-2023-44487)。生产建议 100–128,并额外限制单位时间内的 RST_STREAM 速率。

6. 0-RTT 的重放风险

启用 h3 的 0-RTT 时,非幂等请求可能被重放。要么:

  • 服务端对 0-RTT 中的非幂等请求返回 425 Too Early;
  • 要么实现请求去重(幂等键)。

不要在没有防护的情况下对写接口开 0-RTT。

7. UDP 必须可回落

h3 依赖 UDP/443 可达。必须同时保留 h2/1.1 端点,并确认防火墙放行 UDP 443。只开 h3 会让部分用户完全无法访问。

8. 可观测性要重建

QUIC 加密了传输层元数据,传统抓包分析(RTT、重传、窗口)失效。需要:

  • 启用 qlog(端点导出的结构化传输日志)。
  • 在应用层补齐指标:按协议版本分别统计延迟、错误率、连接复用率。

部署检查清单

  • TLS 1.2+ 且启用 ALPN;h3 需 TLS 1.3。
  • 证书链完整(h2 对 TLS 配置更严,禁用重协商与压缩)。
  • 防火墙放行 UDP 443(h3)。
  • 下发 Alt-Svc,并考虑配置 DNS HTTPS 记录以省掉首访的一跳。
  • MAX_CONCURRENT_STREAMS 有限值 + RST_STREAM 速率限制。
  • 窗口大小按带宽延迟积调整。
  • MAX_HEADER_LIST_SIZE 显式设置(防 HPACK 炸弹)。
  • 撤销域名分片,收敛到单域。
  • 保留 h2 与 1.1 回落路径并实测。
  • 用 curl --http2 / --http3 与浏览器 DevTools 的 Protocol 列逐一验证。

验证命令:

curl -sI --http3 https://example.com | head -1
curl -sI --http2 https://example.com | head -1

收尾

三版协议的关系可以用一句话概括:

HTTP 语义从未改变,改的一直是「怎么把它装进字节」和「这些字节跑在什么之上」。

  • HTTP/2 重写了装法(文本 → 二进制帧 + 多路复用 + 压缩)。
  • HTTP/3 重写了载体(TCP → QUIC),顺带把流管理与流量控制下沉。

理解了这一点,HTTP/1.1 专栏里关于方法、状态码与字段的每一条规则,在 h2 与 h3 上都可以原样复用——那才是 HTTP 真正稳定的部分。

本页目录