nginx启用http/2必须同时满足四重条件:版本≥1.9.5、编译含http_v2模块、openssl≥1.0.2且动态链接正确、listen 443 ssl http2配合tlsv1.2+与alpn支持,缺一则浏览器静默降级至http/1.1。

HTTP/2 在 Nginx 中不会“配了就生效”,必须同时满足版本、模块、OpenSSL 链接、TLS 配置四重条件,缺一环浏览器就 fallback 到 HTTP/1.1,且不报错。
检查 Nginx 和 OpenSSL 是否真支持 HTTP/2
很多人写了 listen 443 ssl http2 却看不到 h2,第一步就卡在底层不兼容。不是配置错了,是环境没跑通。
- 运行
nginx -v,确认输出版本 ≥nginx/1.9.5(推荐1.20.2+或最新稳定版) - 运行
nginx -V 2>&1 | grep -o with-http_v2_module,输出必须是with-http_v2_module(不能为空、不能报错) - 运行
nginx -V 2>&1 | grep -i openssl,确认路径指向你期望的 OpenSSL(如--with-openssl=/usr/local/ssl),且版本 ≥1.0.2e;若显示1.0.1e或指向系统旧库(如 CentOS 7 的/usr/lib64/libssl.so.1.0.2k),即使 Nginx 版本够也无效 - 运行
ldd $(which nginx) | grep ssl,确保链接的是你编译时指定的 OpenSSL 动态库(例如libssl.so.1.1),不是系统默认旧版
配置 listen 指令与必要 SSL 参数
HTTP/2 强制要求 TLS,且依赖 ALPN 协商——这不是“开了 HTTPS 就自动有”的功能,必须显式启用。
-
listen行必须同时含ssl和http2:只写listen 443 http2或listen 443 ssl都会被 Nginx 静默忽略 - 正确写法只有两种:
listen 443 ssl http2(IPv4)和listen [::]:443 ssl http2(IPv6);ssl和http2顺序无关,但缺一不可 -
ssl_certificate和ssl_certificate_key必须指向可读的 PEM 格式文件(不能是 DER 或 PFX) -
ssl_protocols必须包含 TLSv1.2 或更高:ssl_protocols TLSv1.2 TLSv1.3;禁用TLSv1.0和TLSv1.1,否则 ALPN 可能被跳过
验证是否真走 h2,而不是假成功
nginx -t && systemctl reload nginx 成功 ≠ HTTP/2 生效。ALPN 协商失败时,Nginx 会退回到 HTTP/1.1,且完全不提示。
- 浏览器打开 DevTools → Network → 刷新页面 → 右键表头勾选
Protocol,任意请求应显示h2(不是http/1.1) - 命令行验证:
curl -I --http2 https://your-domain.com,返回HTTP/2 200且无重定向才算基础通路正常 - 若仍是 HTTP/1.1,用
openssl s_client -alpn h2 -connect your-domain.com:443 2>/dev/null | grep ALPN查看服务端是否通告ALPN protocol: h2;为空说明后端未启用 ALPN(常见于 CDN 中间层拦截或 OpenSSL 链接错误)
最容易被忽略的点是 OpenSSL 运行时链接版本和 ALPN 实际通告状态——这两者不匹配时,所有配置都形同虚设。别只盯着 nginx.conf,先用 ldd 和 openssl s_client 把底层链路敲实。











