11.2 HTTP/3、QPACK、发现与部署
旧连接在丢包时会拖住同车的请求,信标塔准备试用 HTTP/3,但上线前必须弄清发现、回退和观测方式。
HTTP/3 保留 HTTP method、status、field 和 caching semantics,将 framing/multiplexing 映射到 QUIC。它不是一套新 REST semantics,也不是“任意 HTTP/2 frame 原样搬到 UDP”。
1. HTTP/1.1、HTTP/2 与 HTTP/3 的分层
HTTP/1.1: semantics -> HTTP/1.1 textual framing -> TCP -> IP
HTTP/2: semantics -> HTTP/2 binary frames -> TCP -> IP
HTTP/3: semantics -> HTTP/3 frames -> QUIC -> UDP -> IPHTTP/1.1 可在一条 persistent connection 上处理多个 request,pipelining 也允许先发多 request,只是 response 必须按顺序返回且 ecosystem support 有限。因此“HTTP/1.1 一个 connection 一次只能有一 request”是常见 deployment simplification,不是 wire protocol 唯一能力。
HTTP/2 在同一 TCP connection 上 multiplex HTTP stream,解决 HTTP/1.x response ordering/application framing HOL,但遇到 TCP byte gap 时多条 stream 都要等 kernel 补齐。HTTP/3 借 QUIC stream 减少这个 cross-stream transport HOL。
HTTP/3 不是必然更快。Low-loss low-RTT path、warm TCP/TLS connection、UDP throttling、QUIC CPU/crypto implementation、server scheduling 和 application dependency 都可决定 result。应以 target network/user workload 实测,而不用 protocol name 代替 measurement。
2. HTTP/3 stream type
HTTP request/response 使用 client-initiated bidirectional QUIC stream。Typical sequence:
request stream:
HEADERS -> optional DATA -> optional trailers(HEADERS)
response HEADERS -> optional DATA -> optional trailers(HEADERS)HTTP/3 frame 不与 QUIC packet boundary 对齐。一个 H3 frame 可跨多个 STREAM frame/QUIC packet,一个 QUIC packet 也可携带多条 stream 的 data。
Critical unidirectional streams:
- 每个 endpoint 的 HTTP/3 control stream,携带 SETTINGS、GOAWAY、MAX_PUSH_ID 等;
- QPACK encoder stream;
- QPACK decoder stream。
Critical stream 被关闭是 connection error。Unknown unidirectional stream type 通常要忽略/consume,以允许 extension;不能把所有 unknown type 都当 attack 立即断连,也要用 resource limit 防止 peer 无限开 unknown stream。
3. QPACK 为 QUIC out-of-order stream delivery 设计
HPACK 借 HTTP/2/TCP 的全局 ordered byte delivery 同步 dynamic table update。如果直接将同样 dependency 放到多条独立 QUIC stream,request stream 的 compressed field section 可比 dynamic-table insertion 先到。
QPACK 的两个 endpoint 各自维护 encoder/decoder state 和对端 table view:
- Encoder stream 从 encoder 发 table insertion/duplication/capacity instruction 给 peer decoder;
- Decoder stream 从 decoder 发 section acknowledgment、stream cancellation 和 insert-count increment 给 peer encoder;
- Request stream 上的 field section 携带 Required Insert Count/Base 等 information,表明解码 dependency。
Decoder 如果还没收到必需 insertion,可阻塞该 request stream 的 header decoding。SETTINGS_QPACK_BLOCKED_STREAMS 限制 peer 允许的 blocked-stream 数,encoder 可选 static/literal 表示避免超限。所以 QPACK 是将 compression efficiency 与 HOL risk 变成可控 trade-off,不是完全消除 blocking。
Dynamic table 在每个 direction 的 encoder/decoder pair 中同步,不宜简化成“服务器一张 encoder table、客户端一张毫无关系的 decoder table”。Decoder 必须按 encoder instruction 构建一致 dynamic entries,只是 request stream 不必按全局顺序到达。
4. Discovery:Alt-Svc 是 HTTP field,HTTPS RR 才是 DNS
Origin 可在 HTTP/1.1/2 response 中用 Alt-Svc 宣告 HTTP/3 alternative service:
Alt-Svc: h3=":443"; ma=86400Alt-Svc 是 HTTP response field,不能用 dig 查“Alt-Svc DNS record”。Client 可缓存 alternative service,后续尝试 QUIC;certificate 仍要对 origin identity 有效,不是 Alt-Svc host 说什么就信什么。
DNS SVCB/HTTPS resource record(RFC 9460)也可宣告 service binding、ALPN(如 h3)、port/address hint 等:
dig example.com HTTPSAddress hint 是 hint,client 还要按 record/normal A/AAAA resolution 和 connection policy 处理,不能将 hint 当作 authoritative replacement address。DNSSEC 与 encrypted DNS 的边界也与 7.1 相同。
5. Fallback 要避免 UDP black hole 拖慢 page load
Enterprise network、firewall、NAT、QoS/policer 可阻断或降速 UDP/443。HTTP client 不应把 QUIC 当唯一 path,除非 application contract 本来就只支持 QUIC。Browser 常根据 cached Alt-Svc/HTTPS RR 和 past network behavior 决定 racing/fallback,但 exact timeout 和算法是 implementation policy。
“QUIC 失败后再等很久才串行连 TCP”会引入 protocol fallback penalty。Happy-Eyeballs-style racing、brokenness cache 和 connection reuse 可降低惩罚,但也增加 duplicate handshake/load。要观测 attempted protocol、fallback reason/time 和 final negotiated protocol,不只看最终 response 成功。
6. Load balancer 要能根据 CID 稳定路由
QUIC packet 的 source address 可因 NAT rebinding/migration 变化,只按 five-tuple 将 UDP datagram 分到 backend 会破坏 connection continuity。Common deployment:
- Edge/load balancer 终止 QUIC;
- Load balancer 从 server-issued CID 中解码/rendezvous-hash backend ID,将 packet 转给持有 connection state 的 server;
- Shared/external connection-state store(高成本);
- Stateless reset key 管理,让无 state endpoint 可通知 peer connection 不存在。
CID encoding 会暴露 routing metadata/linkability,需要 encryption/rotation/versioning 和 key lifecycle。QUIC-LB 之类规范给出 load-balanced CID 的通用设计,但 deployment 仍要解决 backend draining、CID issuance/retirement、stateless reset 与 key rotation。
7. 0-RTT 在 HTTP 层的处理
HTTP Early Data 用 Early-Data: 1 将 early request 信息向 upstream 传递,intermediary/origin 如果无法安全处理可返 425 Too Early。Client 收到 425 后应在 handshake 完成后重试,而不是再用 early data 循环重试。
Policy 不应只看 method name:
GET可触发 logging、billing、one-time link 或 non-compliant side effect;PUT在 HTTP semantics 中 idempotent,但 repeated processing 仍可增加 audit/notification cost;- Authentication credential 可在 early data 中被 replay to same service context;
- Distributed anti-replay cache 的 consistency/availability 有 trade-off,不存在不付成本的 absolute replay prevention。
对重要 state-changing request,最稳妥默认是等 1-RTT。确实需要 early data 时,设计 application idempotency key、replay window、credential scope 和 duplicate response semantics。
8. 运行时观测与 packet capture
# 先确认 curl build 是否支持 HTTP/3
curl --version
# 允许 client 选 HTTP/3,具体 behavior 查当前 curl 文档
curl -v --http3 https://example.com/
# 只尝试 HTTP/3,用于区分 QUIC path 是否可用
curl -v --http3-only https://example.com/
# QUIC 通常使用 UDP/443,但不是 protocol 硬编码只能 443
tcpdump -ni any udp port 443System curl 可能没编译 HTTP/3 backend,此时 option 不可用,不代表 server 不支持。Test 要记录 curl/backend version,不强制用某个公网测试站作永久依赖。
QUIC payload/header 大部分 encrypted,passive capture 不像 TCP 那样直接看 HTTP fields。可观测性要结合:
- Application access log/trace;
- QUIC transport metrics:handshake outcome、0-RTT accepted/rejected、PTO/loss、RTT、cwnd/pacing、flow-control blocked、migration/path validation;
- qlog(implementation support);
- TLS key log + Wireshark(只在授权调试环境安全保管 secret);
- Optional spin bit/passive signal,受 privacy/configuration 影响,不能假设始终存在。
9. Capacity 与 DoS boundary
QUIC/TLS handshake 可在 UDP 上对 server 产生 CPU/state cost。Deployment 需要:
- Address-validation/Retry policy;
- Per-IP/prefix/global handshake rate limit;
- 3x amplification compliance;
- Connection/stream/buffer/QPACK table limit;
- Stateless reset token/key protection;
- TLS certificate chain 大小与 handshake fragmentation;
- UDP receive buffer、batching/GRO/GSO 和 worker affinity;
- TCP HTTP/2 fallback capacity,不能因 HTTP/3 launch 就缩没。
Firewall 只“开 UDP/443”不等于部署完成:NAT timeout、load-balancer CID routing、fragment/MTU、QoS、DDoS protection 和 observability 都要经过 pressure/failure test。
10. 验收问题
- HTTP/3 frame、QUIC STREAM frame 和 QUIC packet boundary 为什么不同?
- QPACK 为什么仍可 blocked,
SETTINGS_QPACK_BLOCKED_STREAMS解决什么? - Alt-Svc 与 DNS HTTPS RR 分别从哪个 protocol 获得?
- QUIC load balancer 为什么不应只按 five-tuple 选 backend?
curl --http3-only失败能证明什么,还需要记录哪些 client/environment evidence?- HTTP 425 应如何重试,为什么不能再用 early data?