首页/网络/协议速查/ALPN 应用层协议协商

ALPN 应用层协议协商

在 TLS 握手里就商定上层协议(h2 / http/1.1 / h3),避免多一次往返探测;HTTP/2 浏览器连接基本都靠它。

协议速查网络更新于 2026-10-13

ALPN 是什么

ALPN(应用层协议协商)让客户端在 TLS 握手阶段就声明想用的上层协议(h2、http/1.1、h3),服务器从中选择一个并在握手中确认,从而省掉一次额外的探测往返。浏览器访问 HTTPS 站点时会带上 ALPN,服务器没选到 h2 就自动回落 http/1.1——「HTTP/2 明明开了却没生效」通常要在这一层找原因。

基本信息

作用在 TLS 握手中商定上层应用协议
常见取值h2、http/1.1、h3(HTTP/3 走 QUIC)
规范RFC 7301(ALPN)、RFC 9113(HTTP/2)
协议位置ClientHello 与 ServerHello 的 ALPN 扩展
回落行为服务器未选择时客户端退回 http/1.1
Nginx 相关需启用 http2 参数,且要使用支持 ALPN 的版本

典型使用场景

  • 确认站点是否真正启用 HTTP/2:看 ALPN 是否协商出 h2
  • 排查 CDN 与回源链路:边缘与源站各自可能协商出不同协议
  • 压测与兼容性测试:显式指定 ALPN 值验证服务端行为
  • 排查老客户端兼容问题:不支持 ALPN 的客户端能否正常回落
  • 规划 HTTP/3:确认客户端与服务端是否都声明 h3

测试 ALPN 协商

测试 ALPN 协商
# 显式请求 h2,看服务端是否接受
openssl s_client -connect example.com:443 -alpn h2 </dev/null 2>/dev/null | grep -i alpn
# 用 curl 观察实际协商到的协议
curl -v --http2 https://example.com 2>&1 | grep -i -E 'ALPN|HTTP/2'
curl -sI --http2 https://example.com | head -1
# 同时声明多个协议,验证服务端的选择顺序
openssl s_client -connect example.com:443 -alpn 'h2,http/1.1' </dev/null 2>/dev/null | grep -i alpn
# 检查 Nginx 配置中的 http2 参数
nginx -T 2>/dev/null | grep -n 'http2'

协议标识读法

标识含义端口与传输
h2HTTP/2 over TLS443 走 TCP
http/1.1HTTP/1.1443 走 TCP
h3HTTP/3 over QUIC443 走 UDP
未协商到服务端未选择或未配置客户端回落 http/1.1
HTTP/2 的双向流与多路复用建立在 TLS 之上,客户端必须通过 ALPN 声明 h2 才能启用;只要服务端没有在握手中确认 h2,浏览器就会安静地退回 HTTP/1.1,页面依然可用,因此这个问题容易被长期忽略。
调整 ALPN 或协议版本属于「看起来无害」的改动,但会影响所有客户端:上线前用真实客户端验证(浏览器、curl、移动端 SDK),避免出现特定客户端握手失败的情况。
HTTP/3 的协商方式与 h2 不同:它跑在基于 UDP 的 QUIC 上,同样用 ALPN 声明 h3 标识,端口仍是 443。实践中常在同一个域名上同时提供 h3 与 h2,由客户端自行选择,因此防火墙必须放行 UDP 443,否则 h3 永远不会生效。

易错点

  • 只开 TLS 不协商 ALPN,HTTP/2 永远不会启用,性能优化做了却看不到效果
  • 在代理与源站两层分别配置:边缘声明 h2 而回源用 http/1.1,实际收益与预期不符,需分别核对
  • 忽略 h2 需要 TLS 层配合,误以为在后端应用里开启即可生效
  • 压测工具未声明 ALPN,测出的是 HTTP/1.1 的性能却当作 HTTP/2 的结果

数据来源与参考

  • RFC 7301(ALPN)
  • RFC 9113(HTTP/2)

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌