preconnect 走 http3
内容提要
`<link rel="preconnect">` 无法在 HTML 中声明使用 HTTP/3,只能通过服务端 Alt-Svc 响应头或 DNS 的 HTTPS(SVCB)记录指定 h3 ALPN。前提是启用 DoH、未禁用 QUIC、直连且端口为 443。配置错误会静默降级为 TCP,需用 netlog 排查。
延伸解读
为什么 preconnect 无法在 HTML 中指定 HTTP/3
HTML 的 <link rel="preconnect"> 只能告诉浏览器提前建立连接,但无法声明使用哪种协议。协议选择完全由网络栈根据服务端信息(Alt-Svc 响应头或 DNS 的 HTTPS/SVCB 记录)和本地配置自动决定。因此,开发者无法通过标签属性强制 preconnect 走 HTTP/3,只能通过服务端配置来影响浏览器的决策。
启用 HTTP/3 preconnect 的两个可行路径
实际可用的方案有两种:一是服务端通过 Alt-Svc 响应头声明支持 h3,浏览器缓存后后续 preconnect 会走 QUIC;二是 DNS 的 HTTPS 记录中 ALPN 包含 h3,浏览器在解析时直接选择 QUIC。两者都需要满足特定条件,如开启 DoH、QUIC 未被禁用、直连且端口为 443。force_quic_everywhere 在 Chrome 中已无法通过命令行启用,仅适用于 Cronet 或自编译嵌入方。
配置错误会静默降级为 TCP,需用 netlog 排查
如果 DNS 未返回 h3 ALPN 或查询超时,QUIC 侧会返回 ERR_DNS_NO_MATCHING_SUPPORTED_ALPN,并自动回落到 TCP preconnect,整个过程不会报错。因此,配置错误往往难以察觉,只能通过 netlog 确认实际使用的协议。排查时需检查 DoH 是否开启、DoH 服务器是否支持 type 65、端口是否为 443、ALPN 是否包含 h3、是否直连以及 QUIC 是否被禁用等。
DNS 配置的常见陷阱与限制
使用 DNS HTTPS 记录时需注意:非 443 端口不支持;ALPN 中必须包含 h3,否则会阻止 QUIC;HTTPS 记录的 TTL 会影响整个域名的缓存寿命,建议与 A/AAAA 保持一致;ipv4hint/ipv6hint 在稳定版中不生效。此外,preconnect 的粒度是 origin 级,一旦生效,后续真实请求也会走 h3;UDP 443 被封或代理环境下可能失效;第一次 preconnect 不会立即生效(Alt-Svc 方案需先有真实响应)。
Q&A
如何让 <link rel="preconnect"> 走 HTTP/3?
HTML 层面无法直接声明 preconnect 使用 HTTP/3。只能通过服务端 Alt-Svc 响应头或 DNS 的 HTTPS(SVCB)记录指定 h3 ALPN,浏览器会自动决定是否使用 QUIC。
preconnect 走 HTTP/3 需要满足哪些条件?
需要满足三个条件之一:① 浏览器缓存了站点的 Alt-Svc 响应头(如 Alt-Svc: h3=":443"; ma=86400);② DNS 的 HTTPS 记录中 ALPN 包含 h3;③ 启用 force_quic_everywhere(但 Chrome 无法通过命令行开启)。实际可用的是前两种。
为什么配置了 DNS HTTPS 记录但 preconnect 还是走 TCP?
可能原因包括:未开启 Secure DNS (DoH)、DoH 服务器不支持 type 65 查询、QUIC 被禁用、使用了代理、端口不是 443、ALPN 中未包含 h3、HTTPS 记录 TTL 过短、或 origin 被标记为 QUIC broken。配置错误会静默降级为 TCP,需用 netlog 排查。
如何检查 preconnect 是否真的走了 HTTP/3?
抓取 netlog 是最权威的方法。使用 --log-net-log 参数启动 Chrome,然后在 netlog-viewer 中搜索:HTTP_STREAM_JOB 且 type = preconnect_dns_alpn_h3(方案 B 生效);HTTP_STREAM_POOL_JOB_ALIVE 中 allowed_alpns 含 h3(方案 A 或 B 生效);QUIC_SESSION / QUIC_VERSION_NEGOTIATION 确认握手;HOST_RESOLVER_DNS_TASK 的 transactions_needed 中是否有 HTTPS 类型。
DNS 的 HTTPS 记录中 ALPN 应该怎么写才能让 preconnect 走 h3?
ALPN 必须包含 h3,例如 alpn="h3,h3-29,h2,h1"。注意:如果写了 h2 但没写 h3,反而会堵死 h3,因为 SelectQuicVersion 一旦看到 SVCB 记录就只认列表里的 h3,找不到直接返回 Unsupported。
preconnect 走 HTTP/3 有哪些局限性?
局限性包括:粒度只能是 origin 级,无法只让 preconnect 走 h3;UDP 443 被封会导致 QUIC 握手失败并标记 broken,之后退 TCP;代理环境下基本失效;第一次 preconnect 不生效(方案 A 需先有真实响应);非 https 目标永远不会走 h3;crossorigin 属性无用;连接数会被合并/限流;QUIC 只能开 1 条;QUIC 被禁后不可恢复。