缓存命中率低的常见原因是utm参数混入缓存键;应通过nginx的map指令预清洗$arg,剔除utm_*、v=、_t=等无关参数,再用$clean_args构造proxy_cache_key,并验证x-cache是否均为hit。

缓存键里混入 UTM 参数(如 utm_source、utm_medium、utm_campaign)是缓存命中率低的常见原因。这些参数只用于归因分析,不改变实际返回内容,却会让同一个页面生成 dozens 甚至 hundreds 个不同 key,造成严重缓存碎片。
用 map 指令预清洗 query 参数
Nginx 原生不支持动态剔除部分 query 参数,但可通过 map 在 http 块中定义清洗逻辑:
- 声明一个新变量(如
$clean_args),用正则匹配并过滤掉所有utm_*、v=、_t=、ts=等干扰项 - 保留真正影响响应的参数(如
lang=、device=、version=),其他一概清空 - 示例配置:
map $args $clean_args { default ""; "~^(.*)(?:[&?])(?:utm_[^&=]*|v=|_t=|ts=|random=)[^&]*(?:&|$)(.*)$" "$1$2"; "~^(.*)(?:[&?])(?:utm_[^&=]*|v=|_t=|ts=|random=)[^&]*(?:&|$)" "$1"; }
构造不含 UTM 的 proxy_cache_key
在 location 或 server 块中使用清洗后的变量,避免直接拼接 $args:
- 基础写法:
proxy_cache_key "$scheme$host$uri$is_args$clean_args"; - 若需区分设备或语言,可叠加归一化字段:
"$scheme://$host$uri|$device|$lang|$clean_args"(其中$device和$lang也建议用map提取并标准化) - 切忌把
$args直接放进 key —— 这等于主动引入噪音
验证是否生效
上线后必须验证清洗效果:
- 用
curl -I "https://example.com/?utm_source=wechat&lang=zh"和curl -I "https://example.com/?utm_medium=email&lang=zh"分别请求,观察响应头中X-Cache是否都为HIT - 开启
log_format cache '$cache_key — $upstream_cache_status';,查日志确认两个请求生成的 key 完全一致 - 注意:如果后端对参数顺序敏感(如
?a=1&b=2vs?b=2&a=1),Nginx 无法自动排序,此时应限制缓存范围(例如只缓存静态路径location ~ \.(js|css|png)$)
关键不在加多少变量,而在主动剔除不影响内容的字段。UTM 就是典型该砍掉的“伪维度”。











