把Apache放在业务服务器前面做反向代理,是很多团队的标准做法。但代理层如果只是单纯转发请求,高并发时源站照样会被打满,客户端到代理这一段的传输效率也得不到改善。这篇文章把两件事放在一起讲:一是用mod_cache给代理加上缓存能力,二是梳理HTTP/3 QUIC在Apache侧的落地方式,包括模块现状和一些务实的替代方案。

一、先搭好反向代理加缓存的基础结构
Apache做反向代理依赖mod_proxy系列模块,核心是mod_proxy、mod_proxy_http和mod_cache。缓存有两种存储后端可选:mod_cache_disk把响应写到磁盘,适合大文件、命中率高的场景;mod_cache_socache把缓存放进共享内存(比如memcache后端),适合小对象、低延迟诉求。代理场景下绝大多数团队选disk,因为静态资源和API响应体往往不小,放内存容易吃紧。
基础配置大致是这样的结构:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule cache_module modules/mod_cache.so
LoadModule cache_disk_module modules/mod_cache_disk.so
CacheRoot "/var/cache/apache2/proxy"
CacheDirLevels 2
CacheDirLength 1
CacheMaxFileSize 10000000
<VirtualHost *:443>
ServerName www.ipipp.com
ProxyPreserveHost On
ProxyPass "/" "http://127.0.0.1:8080/"
ProxyPassReverse "/" "http://127.0.0.1:8080/"
CacheEnable disk "/"
CacheHeader On
CacheDefaultExpire 3600
CacheDetailHeader On
</VirtualHost>
几个细节值得注意。CacheEnable disk "/"表示对这个虚拟主机所有路径启用磁盘缓存,粒度可以按路径细分,比如只对/static/启用。CacheDefaultExpire只在响应头里既没有Cache-Control也没有Expires时兜底,正常业务应该让源站输出明确的Cache-Control。CacheHeader打开后,响应里会多一个X-Cache头,值是HIT或MISS,调试期非常有用,上线后建议关掉,避免暴露内部行为。
二、缓存命中条件与常见的踩坑点
很多人配完发现缓存始终MISS,问题多半出在命中条件上。mod_cache默认只缓存GET请求,且要求响应带有明确的过期信息:Expires、Cache-Control里的max-age或s-maxage三者至少其一。源站返回的是Set-Cookie、Vary字段过多、或者状态码是授权相关的,Apache都会谨慎处理。默认可缓存的状态码包括200、203、300、301、410等,POST默认不缓存。如果希望覆盖更多情况,可以用CacheStoreExpired On、CacheIgnoreNoStoreAct On这类指令调整,但要清楚放宽条件的代价是脏数据风险。
Vary头是另一个隐形杀手。如果源站每个响应都带Vary: User-Agent,User-Agent组合近乎无穷,缓存目录会被碎片撑爆,命中率趋近于零。解决办法要么在源站去掉不必要的Vary,要么用CacheIgnoreHeaders Set-Cookie User-Agent让Apache忽略指定头。还可以用CacheLock相关指令做请求合并,防止缓存失效瞬间大量请求同时穿透到源站,也就是常说的dogpile效应。缓存失效时第一个请求回源,其余请求等待它写完缓存再读,这对突发流量的保护非常关键。
验证缓存效果时,用curl连发两次请求看X-Cache从MISS变HIT,再用htcacheclean配合定时任务控制磁盘占用,别忘了给CacheRoot所在分区留够空间并设置合理的清理策略。
三、HTTP/3与QUIC到底解决了什么问题
HTTP/2虽然多路复用解决了应用层的队头阻塞,但传输层仍然是TCP,一个丢包会阻塞整条连接上的所有流。QUIC直接跑在UDP之上,把传输层和加密层合并设计,主要优势有几个:一是彻底消除了TCP层的队头阻塞,丢包只影响对应的流;二是握手合并,TLS 1.3的密钥交换和QUIC握手一次完成,首字节时间明显缩短;三是连接迁移,客户端网络从WiFi切到蜂窝时,凭借连接ID可以不断线重连,移动端体验提升明显。
需要明确的是,HTTP/3改变的是客户端到Apache这一段的传输协议,与后端源站的通信协议无关。也就是说,启用QUIC之后,Apache到后端依然可以走普通的HTTP/1.1或HTTP/2代理转发,缓存逻辑也完全不受影响。协议升级和缓存加速是两个正交的优化维度,可以分开推进。
四、Apache侧的QUIC现状与落地路径
这是必须坦诚说明的部分:Apache HTTP Server对HTTP/3的支持进度偏慢,官方的mod_http3长期处于实验状态,依赖ngtcp2和nghttp3库,配置方式是让Apache监听UDP 443并配合Protocols指令:
LoadModule http3_module modules/mod_http3.so Protocols h2 h3 http/1.1 Listen 443 Listen 443 udp
但要注意,mod_http3至今没有进入默认构建,多数发行版的Apache包不含这个模块,自行编译还涉及OpenSSL对QUIC API的支持问题,生产环境直接上需要承担不小的维护成本。如果一定要在Apache体系里尝鲜,可以考虑自行编译带QUIC支持的OpenSSL分支加mod_http3,但更稳妥的做法是在Apache前面加一层支持HTTP/3的接入点,比如用nginx的QUIC模块、HAProxy 2.6以上版本,或者云厂商的负载均衡来终结QUIC,后端仍然是Apache。这样客户端享受HTTP/3的低延迟特性,Apache继续承担代理和缓存职责,架构上各司其职。
迁移时的兼容性不用担心,QUIC发现UDP 443不通会自动回退到TCP上的HTTP/2或HTTP/1.1,浏览器和服务端之间的协商是渐进式的。验证方式很简单,Chrome打开chrome://version或在开发者工具的协议列里看是否显示h3,命令行可以用支持QUIC的curl构建测试。
五、整合建议与性能核对清单
把前面的内容串起来,一个推荐的生产架构是:最外层是支持HTTP/3的接入层(终结QUIC),中间是Apache反向代理加磁盘缓存,最里面是业务源站。Apache侧重点做三件事:按路径精细化控制CacheEnable范围、设置好过期与清理策略、打开请求合并防穿透。上线前逐项核对这些点,基本能拿到缓存带来的绝大部分收益,同时为HTTP/3的全面普及预留好位置。协议层面的升级可以等mod_http3成熟后再平滑切换,不必为此牺牲当前架构的稳定性。
Apache反向代理HTTP/3QUIC缓存修改时间:2026-09-07 13:36:45