Apache 作为反向代理时,缓存规则一直建立在 HTTP 方法、URI 与响应头之上。HTTP/3 引入 QUIC 后,底层传输从 TCP 切换到 UDP,但这并不改变 HTTP 语义层对可缓存性的判断。真正需要调整的是模块加载方式、监听端口配置以及后端连接管理。本文以 Apache 较新版本的 mod_http3、mod_proxy_http3 与 mod_cache 组合为基础,说明如何让代理缓存同时服务 HTTP/3 客户端,并用 AWK 对日志做命中率分析。

HTTP/3 与 QUIC 对代理缓存的影响
HTTP/3 使用 QUIC 作为传输层,通常情况下客户端会通过 UDP 443 端口发起连接。QUIC 将 TLS 1.3 内置到协议中,通过 ALPN 协商出 h3 标识,并支持连接迁移与 0-RTT 数据发送。这些特性对代理缓存并没有造成破坏性影响,因为缓存模块仍然只关心请求行、URI 以及响应头中的缓存控制信息。UDP 无连接的特点不会改变缓存存储的内容,也不会让缓存键失效。
很多开发者担心 QUIC 的 0-RTT 会让缓存误判,实际不会。0-RTT 发送的是完整的 HTTP 请求,仍然包含请求方法、URI 和头部,代理照常判断是否可以命中缓存。需要留意的是 0-RTT 请求可能被网络重放,因此建议只对 GET、HEAD 这类安全方法开放缓存与 0-RTT 的组合,而对 POST 等非幂等请求关闭 0-RTT 或强制回源处理。
QUIC 的多路复用消除了 TCP 队头阻塞,代理到后端时可以复用一条 QUIC 连接处理多个请求,从而降低建连开销。但连接迁移背后增加了连接 ID 管理,Apache 作为代理需要正确维护后端连接池,否则可能出现迁移后会话丢失或连接失效。实际部署中,应关注后端 QUIC 连接的空闲超时和最大请求数配置,避免连接被过早回收。
Apache 启用 HTTP/3 代理缓存的核心配置
Apache 对 HTTP/3 的支持依赖 mod_http3 与 mod_proxy_http3,底层通常需要 nghttp3 和 ngtcp2 库。缓存部分则继续使用 mod_cache、mod_cache_disk 或 mod_cache_socache。启用模块的写法如下:
LoadModule http3_module modules/mod_http3.so LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http3_module modules/mod_proxy_http3.so LoadModule cache_module modules/mod_cache.so LoadModule cache_disk_module modules/mod_cache_disk.so
前端监听需要同时覆盖 TCP 和 UDP,才能让客户端在 h3、h2 与 http/1.1 之间选择。虚拟主机中可以使用 <VirtualHost> 指令同时监听 443 端口,并通过 Protocols 指令声明支持的协议版本。下面是一个基础配置示例,其中 TLS 1.3 是所有 HTTP/3 连接的最低要求。
<VirtualHost *:443>
ServerName ipipp.com
Protocols h3 h2 http/1.1
SSLEngine on
SSLProtocol -all +TLSv1.3
SSLCertificateFile /etc/ssl/ipipp.com.crt
SSLCertificateKeyFile /etc/ssl/ipipp.com.key
ProxyPreserveHost On
ProxyPass "/" "http3://backend.ipipp.com:443/"
ProxyPassReverse "/" "https://backend.ipipp.com:443/"
</VirtualHost>
后端地址使用 http3:// 前缀时,Apache 会尝试通过 QUIC 回源。如果当前 Apache 版本对 http3:// 前缀支持不完善,也可以将 ProxyPass 写成 https:// 并依赖后端的 Alt-Svc 响应头来协商 HTTP/3。无论哪种方式,都需要确保后端证书在代理侧可验证,并正确加载 SSLProxyEngine。
缓存的启用与传输协议无关。在虚拟主机或目录上下文中加入缓存指令,即可让代理缓存 HTTP/3 响应:
CacheEnable disk / CacheRoot /var/cache/apache2/mod_cache_disk CacheHeader on CacheDefaultExpire 3600 CacheIgnoreHeaders Set-Cookie CacheMaxExpire 86400
上述指令会将所有路径的响应写入磁盘缓存,强制记录缓存头信息,并忽略 Set-Cookie 响应头对缓存的影响。实际使用中,如果后端通过 Set-Cookie 区分用户状态,直接忽略可能导致错误命中,需要配合 Vary: Cookie 或使用 CacheIgnoreHeaders 的精准范围。
缓存键、Vary 响应与 QUIC 连接复用
缓存键的生成仍然基于请求 URI 以及经过处理的 Vary 头。HTTP/3 使用 QPACK 压缩头部,压缩会改变字节表示,但不会改变头部值的逻辑内容。代理缓存必须存储完整的响应头,当请求携带不同的 Accept、Accept-Language 或 User-Agent 时,根据 Vary 头分别维护缓存副本。QPACK 的字典更新不应当影响 Vary 头的比较结果。
缓存过期与验证逻辑同样不受 QUIC 影响。Cache-Control 中的 max-age、no-cache、no-store、private 等指令仍然原样生效。Apache mod_cache 提供了 CacheStoreNoStore 和 CacheIgnoreCacheControl 指令,可以让代理忽略 no-store 或强制缓存,但这种做法可能违背源站语义,只适合内网接口或日志分析类请求。正式环境更推荐通过 Cache-Control: public, max-age=300 明确响应可缓存。
QUIC 连接复用对缓存性能的提升主要体现在回源阶段。代理到后端如果已经建立了可复用的 QUIC 连接,后续请求可以直接发送,无需重新完成 TLS 握手。对于 GET 请求,还可以尝试使用 0-RTT 回源,减少一个 RTT 的延迟。不过 0-RTT 重放风险意味着后端必须保证 GET 请求的幂等性,同时 Apache 需要配置 SSLProxyEngine on 并正确加载 TLS 会话缓存。
缓存策略优化时,可以考虑将内存缓存与磁盘缓存结合使用。mod_cache_socache 可以把热门响应放入共享内存,避免磁盘读取延迟。对于 HTTP/3 这类强调低延迟的场景,内存缓存能够进一步放大 QUIC 连接复用带来的收益。配置示例如下:
CacheEnable socache / CacheSocache shmcb:/var/cache/apache2/shcache(512000) CacheHeader on CacheDefaultExpire 600
当缓存命中时,Apache 会直接使用缓存响应,不再向后端发起 QUIC 连接,这比任何连接复用都更节省资源。因此判断 HTTP/3 代理是否成功,不能只看连接成功率,还要看缓存命中率是否达到预期。
用 AWK 快速统计 HTTP/3 缓存命中率
要分析 HTTP/3 请求是否真正被缓存,需要让访问日志记录协议版本和缓存状态。Apache 支持自定义 LogFormat,可以使用 SSL 协议变量记录 TLS 协议,再通过缓存模块提供的环境变量记录命中状态。下面是一个适合统计的日志格式:
LogFormat "%h %l %u %t \"%r\" %>s %b %{SSL_PROTOCOL}x %{cache-status}e" quic_cache
CustomLog /var/log/apache2/quic_cache.log quic_cache
在这个格式中,第 7 个字段是客户端使用的协议,例如 HTTP/3.0;第 11 个字段是缓存状态,命中时显示为 hit,未命中显示为 miss。日志行看起来大致如下:
127.0.0.1 - - [01/Jan:12:00:00 +0000] "GET /index.html HTTP/3.0" 200 1234 "TLSv1.3" "hit"
利用 AWK 可以快速统计 HTTP/3 请求总数与缓存命中数量。下面这条命令读取日志文件,按字段判断协议和缓存状态,最后输出命中率:
awk '$7=="HTTP/3.0" {h3++} $11=="hit" {hit++} END {print "H3 total:", h3; print "H3 cache hit:", hit; if(h3>0) printf "Hit ratio: %.2f%%\n", hit/h3*100}' /var/log/apache2/quic_cache.log
运行结果会直接显示 HTTP/3 请求总量和缓存命中比例。如果命中率明显低于 HTTP/2 或 HTTP/1.1 场景,可以从响应头入手,检查源站是否错误返回了 private、no-store,或者 Set-Cookie 导致响应不可缓存。也可以进一步用 AWK 统计不同 URI 的命中情况,定位热点资源并调整缓存过期时间。
通过 AWK 做日志分析的优势在于无需额外部署监控系统,适合快速排查和调优。当确认缓存策略合理、命中率提升之后,再观察后端 QUIC 连接数与回源延迟,就可以完整评估 Apache 代理缓存在 HTTP/3 环境下的实际效果。

