Nginx可通过proxy_cache_key结合变量动态生成缓存Key,支持基于URL、参数、Header、Cookie等请求特征精准控制缓存粒度;需用map预处理复杂逻辑,避免敏感信息入Key,并注意参数顺序、长度及安全性。

可以通过 Nginx 的 proxy_cache_key 指令结合变量动态拼接,实现基于请求特征(如 URL、参数、Header、Cookie 等)的缓存 Key 生成,从而精准控制缓存粒度。
使用内置变量组合构建差异化缓存 Key
Nginx 提供大量预定义变量,可直接用于 proxy_cache_key。关键在于识别影响内容响应的请求特征,并将其纳入 Key:
-
区分带参与不带参请求:默认情况下
$scheme$host$request_uri已包含完整 URI(含 query string),但若需忽略某些参数(如 tracking 类),需先用map或rewrite清洗 -
按用户角色缓存不同内容:例如登录态用户与游客看到的页面不同,可加入
$cookie_user_id或$http_authorization -
适配多端响应:通过
$http_user_agent或自定义 Header(如$http_x_device_type)区分 mobile/web/app,避免缓存错乱
用 map 指令预处理复杂逻辑
当缓存策略依赖条件判断(如“仅对 GET/HEAD 请求缓存”“排除含特定 Cookie 的请求”),直接写在 proxy_cache_key 中不可行,需借助 map 提前计算出标准化变量:
示例:对含 preview=true 参数或 X-Debug: 1 Header 的请求,强制不缓存(或打上调试标记):
map $arg_preview:$http_x_debug $cache_bypass {
~*true:.* 1;
~*.*:1 1;
default 0;
}
# 在 location 中配合使用:
proxy_cache_bypass $cache_bypass;
proxy_no_cache $cache_bypass;再比如,提取并规范化设备类型用于 Key:
map $http_user_agent $device_type {
~*mobile|android|iphone mobile;
~*tablet tablet;
default desktop;
}后续即可在 proxy_cache_key 中使用 $device_type。
安全与可维护性注意事项
动态 Key 虽灵活,但易引入隐患:
-
避免敏感信息入 Key:如完整
$cookie_sessionid或$http_authorization可能导致缓存爆炸(每个用户一个 Key)或泄露风险;建议用哈希(md5($cookie_sessionid))或提取标识字段($cookie_uid)代替 -
统一参数顺序提升命中率:客户端可能以任意顺序发送 query 参数(
?a=1&b=2和?b=2&a=1视为不同 URI),Nginx 默认不重排。可通过perl_set或 Lua 模块标准化,或要求上游统一规范 -
Key 长度与字符限制:Nginx 对 cache key 长度无硬限制,但过长会影响性能和日志可读性;避免直接拼接未过滤的原始 Header 值,建议用
map截断或映射为简短代号
验证与调试技巧
确认 Key 生成是否符合预期:
- 启用
log_format记录实际使用的 Key:
log_format cache_log '$remote_addr - $upstream_cache_status "$request" "$upstream_http_content_type" "$proxy_host" "$proxy_cache_key"'; - 用
add_header X-Cache-Key $proxy_cache_key;将生成的 Key 输出到响应头,便于浏览器或 curl 直接观察 - 配合
proxy_cache_valid和proxy_cache_lock,观察HIT/MISS/EXPIRED/STALE状态变化,反推 Key 是否合理收敛


















