HTTP/3 把 HTTP 放在 QUIC 上传输,不再依赖 TCP。QUIC 提供逐流有序交付:一条流缺少某段内容时,另一条流已经完整收到的数据不一定必须跟着等待。它解除的是特定的传输顺序依赖,并没有给每个请求配备独立的拥塞控制器、丢包检测器或确定的完成期限。先区分交付顺序和恢复机制,才能准确理解收益。
交付顺序不等于丢包检测
HTTP/2 的帧共享 TCP 的一个有序字节流。中间缺少一段时,后续字节即使属于另一个响应,也要等缺口补齐才能交给 HTTP。已经交付的内容不会被收回,应用也不会因为出现一次丢包就全部停止。究竟影响哪些请求,要看它们的字节相对缺口处于什么位置,不能笼统说整条连接上的所有工作都同时冻结。
QUIC 在每条流内维护偏移量。当 A 流仍缺少前面的字节时,B 流完整收到的数据可以交付。不过,一个 QUIC 包可以携带多条流的帧,因此丢掉一个包也可能同时影响多条流。需要恢复的信息会装进新包再次发送;包编号与流偏移量承担不同职责,并不是每个流各自重新传送一份独立的旧包。
RFC 9002 按包编号空间区分丢包检测,而不是按 HTTP 请求或流划分。往返时间估计与拥塞控制面向网络路径。逐流流控之外还存在连接级额度,因此共享容量不足或连接额度耗尽,仍会同时拖慢多个流。不能把独立排序扩写成独立带宽,也不能说某条流发生问题时邻居在任何条件下都不受影响。
HTTP 语义与部署边界仍然存在
方法、状态码和表示语义仍属于 HTTP。HTTP/3 改变消息分帧,并使用 QPACK 压缩字段。QUIC 集成 TLS 1.3 认证与包保护;调度和优先级策略仍要决定先发送哪些已经可用的流数据,并不会凭空增加带宽。如果某个字段区段依赖尚未到达的 QPACK 动态表项,它仍然可能等待。因此,去掉 TCP 的跨流顺序约束,并没有消灭协议内部或应用内部的全部依赖,共享数据库锁和服务端工作队列也不会随之消失。
丢包路径可能受益,但应测量真实工作负载,而不是保证所有网页必然加速。处理器成本、握手成功率、调度、可用带宽和客户端实现都会影响结果。比较时要核对同一被测链路实际协商的协议及正文完成情况;边缘节点使用 HTTP/3,不能证明它连接源站时也采用同样协议,更不能凭协议名称推算生产收益。
客户端可以通过 Alt-Svc 等机制发现 HTTP/3。UDP 连通性导致 QUIC 建立失败时,RFC 9114 建议尝试基于 TCP 的 HTTP,但这不是立即且必然回落 HTTP/2 的承诺。客户端策略与服务端实际开放的协议都重要。运营方仍需保留可达的替代路径、正确发布服务公告,并测量失败尝试和回退等待,不能把兼容性解释成部署无需管理。
坏掉的样子
防火墙或中间设备可能阻断 QUIC 流量,也可能影响可用的数据报大小。成功发送服务公告,不代表客户端已经建立 QUIC。应按网络和协议记录失败,并在依赖回退保障可用性之前主动测试它。只有最终页面能打开,还不足以说明失败路径没有引入明显延迟,也不能证明用户实际使用了预期传输。
TLS 恢复可以允许在握手完成前发送零往返应用数据。这不是把 ClientHello 重放一次就自动获得优化;服务端接受的早期请求本身可能被攻击者重放。按 RFC 8470,在没有额外信息时,客户端不得用早期数据发送不安全方法;仅有幂等性质仍不充分。收到 425 后,应在早期数据之外重试,不能把结果不明的购买换成新的业务行动来绕过风险。
连接标识可以帮助地址变化后的连接迁移,但是否能够继续,取决于协议规则、配置、路由和路径验证。NAT 重绑定与主动迁移相关,却不是同一场景。负载均衡器如果丢失连接归属,流量仍会中断;迁移也不是信任任意新地址或跳过验证的许可。手机切换网络可能保留连接,是有条件的能力,不是所有基础设施都自动兑现的保证。
快速验证
将代码保存为 quic_streams.py,使用 Python 3 执行 python3 quic_streams.py。程序不打开套接字。它比较单一有序传输与两条流分别排序时的数据可见性。抽象块携带注明位置的字节,不宣称这些块实现真实包格式或恢复算法,也不虚构某个包在第三个时刻丢失的调度过程。
# Each tuple is a stream name, a one-byte offset, and that byte.
# Chunks are abstract delivery units, not QUIC packets or TCP segments.
def available(chunks, received, separate_streams):
buffered = {"A": {}, "B": {}}
for number, chunk in enumerate(chunks):
if number not in received:
if not separate_streams:
break # One ordered transport cannot expose later chunks.
continue
for stream, offset, byte in chunk:
assert len(byte) == 1
buffered[stream][offset] = byte
result = {}
for stream, offsets in buffered.items():
body = b""
while len(body) in offsets:
body += offsets[len(body)]
result[stream] = body
return result
chunks = [[("A", 0, b"a")], [("A", 1, b"b")],
[("B", 0, b"x")], [("B", 1, b"y")]]
received = {0, 2, 3} # The unit carrying A's second byte is missing.
independent = available(chunks, received, True)
ordered = available(chunks, received, False)
assert independent == {"A": b"a", "B": b"xy"}
assert ordered == {"A": b"a", "B": b""}
print("one missing A byte:", independent, ordered)
complete = {"A": b"ab", "B": b"xy"}
for separate in (False, True):
assert available(chunks, set(range(4)), separate) == complete
print("after repair: both models expose", complete)
# A single missing delivery unit can contain bytes for both streams.
shared = [[("A", 0, b"a")], [("A", 1, b"b"), ("B", 0, b"x")],
[("B", 1, b"y")]]
assert available(shared, {0, 2}, True) == {"A": b"a", "B": b""}
assert available(shared, {0, 1, 2}, True) == complete
# Even an independently ordered stream cannot skip its own missing prefix.
assert available(chunks, {0, 1, 3}, True) == {"A": b"ab", "B": b""}
print("negative controls: shared loss affects both; stream-local gaps still block")
print("delivery-order model only; no loss detector, timer, congestion, or wire test")
A 的第二个字节缺失时,独立排序模型暴露 A 的第一个字节和完整 B;共享有序传输只暴露 A 的第一个字节。补齐缺失块后,两种结果都完整。输出没有任何实测耗时,也没有通过事先写死的完成时间去“证明”一个协议一定更快。
负向检查同样重要:丢失一个同时含 A、B 数据的块,会让两条流都缺少必要前缀;只收到 B 的第二个字节,也不能跳过第一个。实验只展示明确写出的排序假设,没有测量重传时间、拥塞、流控耗尽、QPACK、TLS、迁移或浏览器性能。那些结论需要真实实现与另行获准的网络实验,不能由这个内存模型替代。
延伸阅读
来源
- RFC 9000:QUIC,第 2、4、8–9、12–13 节:排序、流控、迁移、包与重传信息,已核验 2026-10-15。
- RFC 9002:QUIC 恢复,第 6 节:按包编号空间检测丢失及路径级拥塞行为,已核验 2026-10-15。
- RFC 9114:HTTP/3,HTTP 映射、服务发现及 TCP 回退建议,已核验 2026-10-15。
- RFC 9204:QPACK,第 2.1.2 节:阻塞的字段区段,已核验 2026-10-15。
- RFC 9001:QUIC 中的 TLS,第 9.2 节:零往返重放风险,已核验 2026-10-15。
- RFC 8470:HTTP 早期数据,第 4–5 节:方法安全性及 425 重试行为,已核验 2026-10-15。
- Cloudflare:HTTP/3 与 QUIC,协议背景入门,不作为本模型的验证证据,已核验 2026-10-15。