HTTP/3 上线半年:QUIC 在弱网里到底改善了什麼

半年前我们把一个面向移动端的接口切了 30% 的流量到 HTTP/3,想验证两件事:在丢包和高延迟的环境里,QUIC 是否真的比 TCP+TLS 快;以及,切换的代价有多大。这篇文章把当时的观测方法和结果整理一下。

测量方法

客户端是自研的移动 SDK,可以在同一版本里按比例选择 HTTP/2 或 HTTP/3。服务端在同一个 anycast 地址上同时开 UDP 443 和 TCP 443,保证网络路径尽量一致。

关键指标不是平均响应时间——平均值会把问题抹平——而是:

  • p50 / p95 的 TTFB,按客户端估算的丢包率分桶;
  • 连接建立耗时,区分首次连接和 0-RTT 恢复;
  • 传输层重传比例,用来判断改进是来自协议还是来自运气。

结果

丢包 0–1%:几乎没差别

在网络状况良好的情况下,HTTP/3 和 HTTP/2 的 p50 TTFB 差异在 5ms 以内,处于噪声范围。QUIC 的用户态实现反而多了一点 CPU 开销。这个结果符合预期:没有丢包时,两者都只是一次 RTT 的握手加一次请求。

丢包 2%–8%:差距开始出现

这是 QUIC 的主场。TCP 的队头阻塞在丢包时会把后续所有流一起卡住,而 QUIC 的流之间是独立的。我们观察到 p95 TTFB 在这个区间下降了大约 18%–27%,多流并发的小资源请求受益最明显。

高 RTT + 高丢包:0-RTT 的收益被放大

在 RTT 超过 150ms 的链路上,恢复连接的 0-RTT 让首字节时间直接少了一个往返。但要注意重放风险:我们只对幂等的 GET 接口启用了 0-RTT,写操作一律退回 1-RTT。

什么时候 QUIC 反而更慢

  • 服务端 CPU 紧张时。QUIC 的加解密和拥塞控制都在用户态,单核小机器的吞吐会明显低于内核 TCP。我们的 1 核测试机在 200Mbps 左右就开始出现抖动。
  • UDP 被限速或 QoS 降级的网络。部分运营商对 UDP 大包不友好,表现是握手成功但传输速率上不去。
  • MTU 探测失败。路径 MTU 小于 1200 时,QUIC 会直接失败而不是降级,需要客户端有回退逻辑。

工程上的几个决定

最后我们保留了双栈,但把 HTTP/3 的优先级放在“网络质量差”的分支里,而不是无条件优先。具体做法是客户端根据最近几次请求的丢包和 RTT 估计做选择,服务端通过 Alt-Svc 通告能力。

另外,监控上补了一个容易被忽略的指标:QUIC 握手失败率。它不会体现在 HTTP 状态码里,但会实打实地变成用户的等待时间。

QUIC 不是“更快的 TCP”,它是“在坏网络里更不容易崩的传输层”。把它当成银弹,多半会失望;把它当成弱网兜底,收益会超出预期。

← 返回文章列表