Nginx 缓存是否区分查询参数取决于 proxy_cache_key 是否包含 $args 或结构化参数,推荐用 "$scheme$host$request_uri$is_args$args" 并排除敏感参数;需用 proxy_cache_bypass 绕过个性化请求,再通过 map 按参数语义设置差异化缓存时间。
Nginx 默认不区分带不同查询参数的请求,比如 /api/user?id=123 和 /api/user?id=456 若未显式配置缓存键,会被当成同一个 URL 缓存,导致数据错乱。要让缓存真正“识别参数”,关键不是“检测”参数,而是在缓存键(proxy_cache_key)中显式包含参数,并配合绕过逻辑控制缓存行为。
$args 或结构化参数纳入缓存键Nginx 缓存是否区分请求,完全取决于 proxy_cache_key 的构成。若 key 中不含参数,所有参数变体都会命中同一缓存项。
✅ 推荐写法(含标准化参数顺序):
proxy_cache_key "$scheme$host$request_uri$is_args$args";
request_uri 已包含原始路径和查询串,$is_args$args 确保空参数时不会多出 ?,语义清晰且兼容性好。
⚠️ 避免直接用 $request_uri 单独作为 key:
它不区分大小写,且对参数顺序、编码格式不敏感(如 a=1&b=2 和 b=2&a=1 可能被视作相同),易引发冲突。
? 对敏感参数(如 token、session_id)需排除在 key 外:
set $cache_args "";if ($args ~ "^(.*&)?(token|sid)=[^&]*(?:&.*)?$") { set $cache_args $1$3;}proxy_cache_key "$scheme$host$request_uri$is_args$cache_args";
更稳妥的做法是用 map 预处理(避免 if 在 location 外的风险),或由后端统一签名后透传(如 X-Req-Sign)。
有些参数天然表示个性化或临时状态,这类请求不应进缓存,应通过 proxy_cache_bypass 实时拦截:
用户身份类参数直接绕过:
proxy_cache_bypass $arg_user_id $arg_session $cookie_auth_token;
只要任一变量非空,就跳过缓存,直连后端。
统一管理登录态接口:
location /user/ { proxy_cache_bypass $arg_token $cookie_jwt; proxy_cache_valid 200 2m;}
单纯“识别参数”不够,还要按参数含义做策略分级。例如:
/product?id=1001)可缓 1 小时; /order?user_id=123)禁止缓存。用 map 提前打标,再结合 proxy_cache_valid:
map $args $cache_policy { "~*id=d+" "public_1h"; "~*user_id=" "private_0s"; default "default_5m";}location /api/ { proxy_cache_valid 200 $cache_policy;}
注意:proxy_cache_valid 支持变量,但只接受时间值(如 "1h"、"0s"),不能是字符串或布尔。
不复杂但容易忽略