FastCGI缓存键默认不含$args,导致相同URL不同参数被误判为同一缓存;应显式添加$args并用map过滤utm_*等无关参数,确保键唯一性与业务一致性。

FastCGI 缓存键(fastcgi_cache_key)默认不包含请求参数(如 GET 查询字符串),因此相同 URL 的不同参数会被缓存为同一份内容,导致缓存污染或返回错误结果。要实现“按参数区分缓存”,关键是在 fastcgi_cache_key 中显式拼接请求参数,并确保其顺序、编码和过滤逻辑可控。
用 $args 包含完整查询参数
$args 是 Nginx 内置变量,代表原始未解码的查询字符串(例如 a=1&b=2&c=3)。它天然保留参数顺序与原始格式,适合直接用于缓存键:
fastcgi_cache_key "$scheme$request_method$host$request_uri$args";
⚠️ 注意:$args 末尾可能带 &(如 ?a=1&),且大小写、空格、编码差异(如 %20 vs 空格)会影响键唯一性。若后端对参数顺序不敏感,建议先标准化。
按字典序排序并标准化参数(推荐)
避免因参数顺序不同(如 ?b=2&a=1 vs ?a=1&b=2)生成不同缓存键,可借助 Nginx 的 map 指令 + Lua(需 lua-nginx-module)或在应用层处理。更轻量方案是使用 $query_string(同 $args)配合固定排序逻辑——但 Nginx 原生不支持排序,因此常见做法是:
- 只缓存明确需要参数区分的路径(如加
location ~ \.php$限定) - 用
map提取关键参数,忽略无关项(如分页、追踪参数) - 将必要参数按固定名拼接,强制顺序(如
a=$arg_a&b=$arg_b)
过滤和清理无意义参数
去除 utm_*、ref=、_t= 等不影响业务逻辑的参数,防止缓存碎片化:
map $args $clean_args {
default "";
"~^(.*&)?(utm_[^&]+&?)+(.*)?$" "$1$3";
"~^(.*&)?(ref|_t|fbclid)=[^&]+&?(.*)?$" "$1$3";
}
fastcgi_cache_key "$scheme$request_method$host$request_uri$clean_args";
该 map 使用正则匹配并剔除指定参数,注意需多次匹配才能清除多个干扰项;生产环境建议用 Lua 或应用层统一处理更可靠。
区分大小写与编码一致性
Nginx 变量本身不自动解码 URI,$args 中的 %20 和空格被视为不同字符串。若后端统一解码,缓存键也应保持一致:
- 避免在键中混用
$args和手动decode(Nginx 不支持原生命令) - 确保所有入口(PC/移动端、API网关)对参数编码方式统一
- 测试时用
curl -v "http://x/?q=hello%20world"和curl -v "http://x/?q=hello world"验证是否命中同一缓存


















