Apache从2.4.17开始通过mod_http2模块引入HTTP/2支持。与HTTP/1.1不同,HTTP/2并不是在独立的TCP端口上运行,而是在TLS握手阶段利用ALPN扩展进行协议协商。客户端在ClientHello消息中携带自己支持的协议列表,例如h2、http/1.1,服务器端从双方交集里选择一个协议。如果客户端不支持ALPN、不支持h2,或者服务器端没有声明h2,那么连接就会自然降级到HTTP/1.1。这种降级不需要重定向,也不改变访问端口,因此对用户完全透明。

这里需要澄清一个常见误解:HTTP/1.1明文连接可以通过Upgrade头升级到h2c,但生产环境中浏览器只支持TLS上的h2,并不使用h2c升级。因此当讨论Apache的HTTP/2降级时,核心是TLS ALPN协商结果。如果服务器只配置了h2而没有声明http/1.1,不支持HTTP/2的客户端会直接握手失败,而不是自动回落。为了避免这种兼容性风险,Apache配置中应当同时声明h2和http/1.1。
一、Apache中的协议协商与降级触发条件
Apache的mod_http2模块在处理HTTPS连接时,会读取TLS握手过程中确定的ALPN协议。虚拟主机指令Protocols决定了服务器对外公布的协议集合。默认情况下,只要启用了mod_http2并且SSL证书配置正确,Apache就会在ALPN中提供h2和http/1.1两个选项。客户端可以选择h2,也可以根据自身能力选择http/1.1。如果客户端发送的ALPN列表里没有h2,那么服务器只能返回http/1.1,这就是最常见的降级场景。
降级触发条件主要有以下几种:客户端操作系统或浏览器版本过旧,不支持ALPN扩展;客户端虽然支持ALPN,但只接受http/1.1;服务器使用的OpenSSL版本低于1.0.2,无法提供ALPN能力;Apache没有加载mod_http2模块;管理员在虚拟主机配置中显式移除了h2;或者正在使用prefork MPM模式。还有一种情况是HTTP/2连接建立之后发生协议错误,客户端主动重新发起HTTP/1.1请求,这属于应用层回落,和前几类TLS协商降级不同。
判断连接最终使用了哪种协议,可以从抓包中的ALPN扩展、服务器日志以及浏览器开发者工具入手。ALPN协商失败时,服务器日志里通常会出现NO_ALPN或协议回退信息。理解这些触发条件有助于定位为什么某个站点明明开启了HTTP/2,但实际访问却长期停留在HTTP/1.1。
二、Apache启用HTTP/2并保留HTTP/1.1降级的配置
要让Apache同时支持HTTP/2和HTTP/1.1,首先需要确认当前MPM模式。mod_http2依赖mpm_event或mpm_worker,prefork模式无法提供真正的HTTP/2处理。可以使用httpd -V检查MPM类型,如果看到prefork,需要切换到mpm_event或mpm_worker后再加载http2模块。常见的配置片段如下:
LoadModule http2_module modules/mod_http2.so
<VirtualHost *:443>
ServerName www.ipipp.com
Protocols h2 http/1.1
ProtocolsHonorOrder off
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/server.crt
SSLCertificateKeyFile /etc/pki/tls/private/server.key
DocumentRoot /var/www/html
<Directory /var/www/html>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
上面配置中的Protocols h2 http/1.1是降级兼容的关键。它表示服务器在ALPN中同时公布两种协议,允许客户端优先选择,也允许只支持HTTP/1.1的客户端继续使用原有协议。默认情况下ProtocolsHonorOrder为off,表示客户端优先级占主导;如果设置为on,服务器会按照Protocols中的书写顺序优先选择h2。这两种设置都不会阻止降级,但会影响较新客户端在支持多个协议时的选择行为。
证书配置和TLS版本也很重要。HTTP/2要求TLS 1.2或更高版本,并且证书必须有效。如果终端使用过旧的TLS版本,服务器可能直接拒绝连接,而不是降级到HTTP/1.1。因此,在正式启用HTTP/2前,应当检查OpenSSL版本和SSLCipherSuite设置,避免因为密码套件问题导致握手失败。完成配置后执行apachectl configtest验证语法,再优雅重启Apache使配置生效。
三、降级行为验证与常见问题排查
验证Apache是否按预期进行HTTP/2协商,可以使用curl命令。curl 7.43及以上版本支持HTTP/2,通过--http2参数可以强制尝试h2协商。下面几条命令分别用于检查默认协议版本、强制HTTP/1.1以及仅查看协商后的版本:
curl -I --http2 https://www.ipipp.com/
curl -I --http1.1 https://www.ipipp.com/
curl -sI https://www.ipipp.com/ -o /dev/null -w '%{http_version}n'
如果输出结果为2,说明当前连接使用了HTTP/2;输出1.1则说明发生了降级或服务器没有启用h2。浏览器的开发者工具同样可以直观看到每项请求的协议列,在Network面板中勾选Protocol后即可查看。如果浏览器显示http/1.1而预期是h2,需要检查证书是否有效、ALPN是否被中间设备剥离、Apache模块是否加载成功以及MPM模式是否正确。
打开http2调试日志可以进一步定位原因。在Apache配置中加入LogLevel http2:debug,并指定ErrorLog路径,重启后访问站点,日志中会记录ALPN协商详情。常见输出包括h2_session: ALPN selected h2,表示协商成功;如果出现NO_ALPN,则说明客户端没有提供ALPN扩展,连接自然使用HTTP/1.1。根据日志信息可以区分是客户端能力不足还是服务器配置遗漏。
还有一个容易被忽略的方向是反向代理。当Apache作为客户端访问后端HTTP/2服务时,需要mod_proxy_http2模块,ProxyPass可以使用h2://或h2c://前缀指定后端协议。如果后端不支持HTTP/2,代理连接也会回退到HTTP/1.1。此时日志会记录与后端协商失败的信息,和面向浏览器端的降级是不同层面。无论哪种场景,保留HTTP/1.1兼容路径都是生产环境平滑启用HTTP/2的基础,也是避免部分旧设备无法访问的重要策略。
HTTP/2降级Apache HTTP/2配置TLS ALPN协商修改时间:2026-08-20 11:53:54