不能只用 $host + $request_uri 作缓存键,否则会导致 HEAD/GET 缓存污染、未区分用户身份、UTM 参数引发缓存碎片;应增强为包含 $request_method、清洗后的 $clean_args 及租户标识的组合。

直接用 $request_uri 和 $host 组合做缓存键,看似简单,但容易踩坑——它只解决了“域名不同就分开缓存”的基础需求,却忽略了方法、身份、参数语义等关键维度。真正安全有效的组合,必须按业务意图补全上下文。
为什么不能只拼 $host + $request_uri
默认组合如 proxy_cache_key "$host$request_uri"; 会带来三类风险:
- GET 和 HEAD 请求共用同一份缓存,HEAD 命中后可能把不带响应体的缓存覆盖给后续 GET,导致页面空白
- 同一 URL 下,登录用户和游客看到的内容不同(比如“我的订单”按钮),但缓存没区分 Cookie,结果游客看到登录态页面
- 带 UTM 参数的分享链接(如
?utm_source=weibo)和纯净链接被当成两个 key,造成缓存碎片,命中率骤降
合理增强:加方法、控参数、稳租户
在保留 $host 和 $request_uri 的基础上,至少补充三项:
-
强制区分请求方法:加上
$request_method,避免 HEAD/GET/POST 相互污染。尤其对支持条件请求(如If-None-Match)的接口很重要 -
清洗查询参数:不用原生
$args,改用预处理后的变量。例如在 http 块中定义:
map $args $clean_args {
~^(.*&)?utm_[^&]+(&.*)?$ "$1$2";
~^(.*&)?ts=[^&]+(&.*)?$ "$1$2";
default $args;
}
再写 key:"$host$request_uri$is_args$clean_args" -
多租户场景必加租户标识:若通过子域识别租户(如
tenant-a.api.example.com),应先用server_name ~^(?<tenant>[^\.]+)\.api\.example\.com$</tenant>提取,再写成"$tenant|$host|$request_method|$request_uri",确保 tenant-a 和 tenant-b 完全隔离
什么时候可以简化?静态资源专用路径
如果仅用于纯静态内容(如 /static/、/images/ 下的文件),且确认无身份差异、无参数语义、无协议混用,那么 "$host$request_uri" 是可接受的底线方案。但仍建议加上 $scheme,防止 HTTPS 页面里误加载 HTTP 缓存引发混合内容警告。
例如:"$scheme$host$request_uri" —— 这是静态资源缓存最简且稳妥的起点。


















