QUIC 协议由 Google 提出,后来被 IETF 标准化为 HTTP/3 的传输层基础,它基于 UDP 实现了可靠传输、多路复用与内建的 TLS 1.3 加密。Apache 作为老牌 Web 服务器,虽然原生对 HTTP/3 的支持起步较晚,但从 2.4.x 后期的实验模块开始,已经可以通过第三方补丁与 ngtcp2、nghttp3 库组合实现 QUIC 传输。本文将以 deepin 发行版为例,完整演示如何在 Apache 上同时启用反向代理、磁盘缓存与 HTTP/3 支持,并给出经过验证的配置与调优思路。

一、为什么 HTTP/3 与 QUIC 值得投入
传统的 HTTP/2 跑在 TCP 之上,所有流共享同一条 TCP 连接。一旦某个数据包丢失,TCP 的重传机制会阻塞整条连接上的所有流,这就是著名的 TCP 层队头阻塞问题。QUIC 直接在 UDP 之上重新实现了可靠传输,每个流独立进行流量控制与重传,丢包只会影响发生丢包的那一个流,其余流继续正常收发数据,弱网环境下的页面加载体验改善非常明显。
其次,QUIC 将 TLS 1.3 握手融合进连接建立过程,一次往返就能完成加密协商,配合 0-RTT 恢复机制,重复访问的客户端甚至可以在第一个数据包里就携带业务请求。对于移动端用户频繁切换网络的场景,QUIC 还支持连接迁移,通过 Connection ID 标识连接而不是四元组,用户从 Wi-Fi 切到 4G 时连接不会中断。
需要指出的是,HTTP/3 的收益在直连场景最明显。如果 Apache 前面还有一层不支持 QUIC 的负载均衡或 CDN,客户端的 QUIC 请求会在中间被降级为 HTTP/1.1 或 HTTP/2,终端链路的优化就无从谈起。因此在架构设计时,要么让 Apache 直接面向客户端,要么确保整个链路都具备 QUIC 透传能力。
二、Apache 代理与缓存模块的协作原理
Apache 的反向代理能力由 mod_proxy 提供,配合 mod_cache 与 mod_cache_disk 可以将后端响应缓存到本地磁盘。当客户端请求到达时,Apache 先检查缓存是否命中,命中且未过期则直接返回副本,完全不必把请求转发给上游的 Tomcat、uWSGI 或 Node.js 进程,这能显著降低后端压力和整体响应延迟。
缓存模块的核心是 key 的构造与新鲜度判定。默认情况下 mod_cache 使用完整的请求 URL 作为缓存 key,同时尊重后端返回的 Cache-Control、Expires、ETag、Last-Modified 等响应头。如果后端应用没有输出任何缓存头,可以通过 CacheEnable 加上 CacheDefaultExpire、CacheLastModifiedFactor 强制生成一个估算的过期时间。
下面是一段可直接使用的虚拟主机配置示例,将动态请求代理到后端 8080 端口,并对可缓存内容启用磁盘缓存:
# 启用必要模块(deepin 下可执行 a2enmod proxy proxy_http cache cache_disk headers)
LoadModule proxy_module modules/mod_proxy.so
LoadModule cache_module modules/mod_cache.so
LoadModule cache_disk_module modules/mod_cache_disk.so
<VirtualHost *:443>
ServerName www.ipipp.com
ProxyPreserveHost On
ProxyPass /api/ http://127.0.0.1:8080/api/
ProxyPassReverse /api/ http://127.0.0.1:8080/api/
# 开启磁盘缓存,指定缓存目录
CacheEnable disk "/"
CacheRoot "/var/cache/apache2/proxy"
CacheDirLevels 2
CacheDirLength 1
CacheDefaultExpire 3600
CacheMaxFileSize 5000000
CacheIgnoreNoLastMod On
# 明确禁用对 Set-Cookie 响应的缓存,避免串号
Header unset Set-Cookie env=dont-cache
</VirtualHost>这段配置中有几个容易踩坑的点。一是 Set-Cookie 头的处理,凡是携带会话 Cookie 的响应默认不会被缓存,这是好事,但如果你确认某些接口的 Cookie 与内容无关,可以用 CacheIgnoreHeaders Set-Cookie 放宽限制,务必确认不会造成用户数据串号。二是缓存目录的磁盘空间要有上限规划,建议配合 htcacheclean 定时清理过期条目,否则磁盘写满后整个站点会异常。
三、deepin 环境编译启用 HTTP/3 支持
deepin 基于 Debian,软件源中的 Apache 通常未包含 HTTP/3 模块,因此需要从源码编译。整体思路是:先安装 nghttp3 与 ngtcp2 两个 QUIC 协议库,再打上 Apache 官方仓库中的 mod_http3 补丁,最后重新编译 httpd。
第一步安装编译依赖与协议库:
# 安装基础编译工具与依赖
sudo apt update
sudo apt install build-essential cmake ninja-build pkg-config \
libssl-dev libevent-dev libtool autoconf git
# 编译安装 nghttp3
git clone --depth 1 -b v1.3.0 https://github.com/ngtcp2/nghttp3
cd nghttp3 && autoreconf -i && ./configure --enable-lib-only \
--prefix=/usr/local
make && sudo make install
# 编译安装 ngtcp2(含 quictls 兼容层)
git clone --depth 1 -b v1.4.0 https://github.com/ngtcp2/ngtcp2
cd ngtcp2 && autoreconf -i && ./configure --enable-lib-only \
--with-openssl --prefix=/usr/local
make && sudo make install
sudo ldconfig第二步下载 Apache 源码与 HTTP/3 补丁。由于 mod_http3 的开发主线在 Apache 的实验分支上,编译时务必让模块版本与 httpd 版本匹配,否则会出现符号缺失导致加载失败。配置时需要启用 http3 模块并声明 quic 相关的头文件路径:
cd httpd-2.4.x
./configure --prefix=/usr/local/apache3 \
--enable-http3 \
--with-nghttp3=/usr/local \
--with-ngtcp2=/usr/local \
--enable-ssl --enable-so --enable-proxy --enable-cache \
--enable-cache-disk
make -j$(nproc) && sudo make install第三步修改监听指令与站点配置。QUIC 走 UDP 443 端口,Apache 需要同时监听 TCP 与 UDP 才能提供 HTTP/3 服务,并在站点中通过 Protocols 指令声明协议协商优先级:
Listen 443
Listen 443 udp # UDP 监听由 mod_http3 接管
<VirtualHost *:443>
ServerName www.ipipp.com
Protocols h3 h2 http/1.1
SSLEngine on
SSLCertificateFile /etc/ssl/certs/site.pem
SSLCertificateKeyFile /etc/ssl/private/site.key
# Alt-Svc 头告知浏览器可以升级到 HTTP/3
Header always set Alt-Svc 'h3=":443"; ma=86400'
</VirtualHost>这里的 Alt-Svc 头非常关键。浏览器不会一开始就用 QUIC,首次访问走 TCP 的 HTTP/2,收到 Alt-Svc 响应头之后才会在后续请求中尝试 HTTP/3,缓存有效期由 ma 参数控制。如果浏览器始终没有切换到 h3,优先检查防火墙是否放行了 UDP 443,这是部署中最常见的问题。
四、验证与性能调优
部署完成后,可以用 curl 验证 QUIC 链路是否真正生效,新版 curl 需要 --with-ngtcp2 或 --with-openssl-quic 编译选项:
# 强制使用 HTTP/3 访问 curl -I --http3-only https://www.ipipp.com/ # 查看协商过程(-v 输出中应出现 QUIC handshake 与 h3 字样) curl -v --http3 https://www.ipipp.com/api/list
缓存效果可以通过 apachectl 查看运行状态,也可以观察 CacheRoot 目录中文件数量的增长趋势,更严谨的方式是在响应头中注入 HIT 或 MISS 标记:
# 需要加载 mod_cache 的状态钩子
CacheDetailHeader on
# 或在日志中记录缓存命中情况
LogFormat "%h %U %>s cache:%{CACHE_STATUS}e" cachetrack
CustomLog logs/cache.log cachetrack调优方向主要有三个。第一,命中率优先于协议升级,一个命中缓存的 HTTP/2 响应往往比回源的 HTTP/3 响应更快,因此先根据访问日志统计热点 URL,合理划分 CacheEnable 的作用范围。第二,QUIC 对 CPU 的消耗高于 TCP,单连接的加解密开销更大,建议开启 KeepAlive 与连接数限制,避免海量短连接拖垮小规格服务器。第三,deepin 桌面版默认的 power-profiles 会影响网卡中断分布,生产部署建议使用服务器模式或手动固定 CPU 频率,保证 UDP 收发的稳定性。
总体来说,Apache 加上 HTTP/3 支持后依然保持了配置驱动的传统风格,运维人员可以在不改动后端应用的前提下,仅通过前端层就完成协议升级与缓存加速。deepin 作为国产化替代环境,其 Debian 血统使得整个编译部署流程与主流发行版高度一致,踩坑成本不高,值得在实际项目中尝试。
Apache代理缓存HTTP/3QUIC修改时间:2026-09-02 18:51:15