apache mod_cache需通过mod_rewrite标准化url并用cachekeybaseurl剔除utm_*、v、ts等无意义参数,保留page、category等业务参数;配合cacheignoreheaders set-cookie和cacheignorenolastmod,确保java后端返回cache-control: public, max-age=3600方可精准缓存。

Apache mod_cache 默认把完整 URL(含所有查询参数)作为缓存键,导致 /api/user?id=123 和 /api/user?id=456 被视为两个完全不同的资源,哪怕后端实际返回相同内容。要实现“精准命中”与“隔离”,关键不是笼统忽略全部参数,而是区分哪些参数影响响应、哪些只是干扰项——比如 utm_source、v、ts 这类不改变内容的追踪或防缓存参数,应剔除;而 page、category 这类业务参数必须保留。
用 mod_rewrite 标准化 URL,再交由 cachekeybaseurl 处理
Apache 本身不支持动态剔除部分 query string,但可通过 mod_rewrite 提前重写 URL,再配合 CacheKeyBaseURL(需 Apache ≥ 2.4.11)让缓存模块基于标准化后的 URL 生成键值。
- 启用必要模块:
mod_rewrite、mod_cache、mod_cache_disk(或mod_cache_socache) - 在虚拟主机或目录配置中添加重写规则,例如过滤掉
utm_*、v、ts、_t等无意义参数:
RewriteEngine On
# 匹配并移除 utm_*、v、ts、_t 等参数,保留其余部分
RewriteCond %{QUERY_STRING} ^(.*)(&)?(utm_[^&]+|v|ts|_t)=[^&]*(.*)$
RewriteRule ^(.*)$ $1?%1%3 [N,R=301]
# 清除末尾多余的 & 或 ?
RewriteCond %{QUERY_STRING} ^(.*)&$
RewriteRule ^(.*)$ $1?%1 [N,R=301]
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^(.*)$ $1? [R=301,L]
注意:上述是跳转写法,生产环境建议用 [E=QS_CLEAN:%1%3] 设置环境变量 + RewriteRule ... [E=...] 配合 CacheKeyBaseURL 实现内部重写,避免真实 301。
启用 CacheKeyBaseURL 并绑定清理后的 query string
CacheKeyBaseURL 允许你指定一个“基础 URL”用于生成缓存键,它会忽略原始请求中的 query string,改用你提供的字符串(可来自环境变量)。
- 先通过
RewriteRule提取干净的 query string 并存入环境变量,如E=CLEAN_QS:%1%3 - 再设置:
CacheKeyBaseURL "%{REQUEST_URI}?%{ENV:CLEAN_QS}" - 确保该指令作用于缓存生效路径下(如
<location></location>),且不能放在.htaccess中(仅主配置或虚拟主机有效)
配合 CacheIgnoreHeaders 和 CacheIgnoreNoLastMod 控制缓存准入
即使 URL 标准化了,如果后端响应带 Set-Cookie 或缺失 Last-Modified,mod_cache_disk 仍可能拒绝缓存。
- 加
CacheIgnoreHeaders Set-Cookie:允许缓存带 Cookie 头的响应(适用于只读 API) - 加
CacheIgnoreNoLastMod On:不强制要求Last-Modified或ETag,只要响应头有Cache-Control: public, max-age=3600就可缓存 - Java 后端必须显式返回
Cache-Control: public, max-age=3600,仅max-age不够,private或无public会被跳过
验证是否真正命中:看 X-Cache 和日志
不要只看响应头有没有 X-Cache: HIT,还要确认它是否来自你预期的路径和键。
- 开启
CacheLock on和CacheLockMaxAge 5可防止并发回源 - 在
CacheRoot目录下检查缓存文件结构,路径应反映标准化后的 URL - 用
curl -I http://host/api/list?v=123&utm_medium=email和curl -I http://host/api/list?v=456&ts=12345对比响应头中的X-Cache和Age字段是否一致且递增










