开了 HTTP/3 却没生效?nginx 上 QUIC 的四道关卡

开了 HTTP/3 却没生效?nginx 上 QUIC 的四道关卡

一、先搞清版本与前提

nginx 从 1.25.0 起支持 QUIC 与 HTTP/3,并且已经包含在 Linux 的二进制包里。也就是说,如果你用的是较新的发行版软件源,可能不需要自行编译。

QUIC 依赖 TLS 1.3,而 TLS 1.3 在 ssl_protocols 指令里默认启用——这一点经常被误解为"要额外打开",其实多数时候不用动。

二、第一道关卡:加密库

这是最容易卡住的地方。原文建议使用 OpenSSL 3.5.1 或更高版本编译;低于这个版本时会退回到兼容层,而兼容层不支持 early data(0-RTT)。除此之外,也可以用 BoringSSL、LibreSSL 或 QuicTLS 的预编译库来编译。

自建时要显式启用 HTTP/3 模块,常规方式是配置阶段加上 --with-http_v3_module,并按所选库指定头文件与链接参数,然后 make 编译安装。

加密库后果
OpenSSL 3.5.1+完整支持,含 early data
低版本 OpenSSL走兼容层,early data 不可用
BoringSSL / LibreSSL / QuicTLS可作为替代方案编译

三、第二道关卡:运行时链接的是哪个库

编译时用对了库,不等于运行时加载的还是它。原文特意强调:确认 nginx 在运行时使用的是正确的 SSL 库,用 nginx -V 能看到当前实际使用的版本。

这一步在容器和多版本共存的服务器上尤其重要:同一条命令,在不同环境里链接的库可能完全不同。

四、第三道关卡:监听与四个开关

启用 HTTP/3 的方式是在 listen 指令上加 quic 参数,指定在该端口上跑 QUIC。多 worker 场景还要配合 reuseport,否则行为不符合预期。

  • quic_retry on:启用地址验证,减少伪造源地址滥用;
  • ssl_early_data on:启用 0-RTT;
  • quic_gso on:启用 GSO(通用分段卸载),这是 Linux 特有优化,默认关闭,需网卡支持;
  • quic_host_key:为各类令牌设置主机密钥。

四个开关里,"默认关闭"的 GSO 最容易被忽略:不开也能跑,开了才吃满性能。

五、第四道关卡:客户端其实没在发 QUIC

服务端配好了,客户端还在用 HTTP/2——这是第二种常见误判。原文的建议是:先用简单的命令行客户端(如 ngtcp2)验证服务端配置是否正确,再去用真实浏览器测试,因为浏览器对证书相当挑剔。

六、排障顺序:按这五步走

  1. 确认编译时带了正确的加密库;
  2. 用 nginx -V 确认运行时用的也是它;
  3. 确认客户端确实在用 QUIC 发请求;
  4. 先用命令行客户端验证,再上浏览器;
  5. 编译带调试支持,翻调试日志——所有相关消息都带 quic 前缀,容易过滤。

需要更深排查时,可以打开 QUIC 调试宏(报文、帧、内存分配、加密四个方向),配合调试构建查看细节。这类开关只在排障时开,长期开启会产生大量日志。

一句话总结:QUIC 的问题九成发生在编译与链接阶段,而不是配置文件里。先确认"用的是哪个库",再看"开了哪些开关"。