Nginx 中 map 指令可基于 Cookie 提取 uid、device 等字段映射为变量,用于 proxy_cache_key 实现缓存隔离,并通过 proxy_cache_bypass 控制灰度绕过,需在 http 块定义、正则谨慎编写、配合日志调试。

在 Nginx 中,map 指令可以基于 Cookie 内容(如用户身份、设备类型、灰度标识等)生成变量,再结合 proxy_cache_key 或 proxy_cache_bypass 实现缓存隔离——让不同用户或场景命中各自独立的缓存副本,避免缓存污染或权限泄露。
提取关键 Cookie 值并映射为缓存维度变量
先从 $http_cookie 中提取目标字段(如 uid、device、env),用正则匹配后映射为可参与缓存键构建的变量。注意:必须在 http 块中定义,且不能在 server 或 location 中直接写 map。
示例:区分登录用户与游客,并按设备类型细分缓存
http {
# 提取 uid(支持 uid=123 或 uid="456")
map $http_cookie $cache_uid {
~*uid=(?:["']?)(\d+)(?:["']?) $1;
default "guest";
}
<pre class="brush:php;toolbar:false;"># 提取 device 类型(mobile/tablet/desktop)
map $http_cookie $cache_device {
~*device=mobile "m";
~*device=tablet "t";
default "d";
}
# 组合维度:uid + device 决定缓存隔离粒度
map $cache_uid$cache_device $cache_key_suffix {
"" "";
default "_$cache_uid_$cache_device";
}}
构造带隔离标识的 cache_key
将 map 生成的变量注入 proxy_cache_key,确保相同 uid+device 的请求共享缓存,不同组合完全隔离。注意保留原始 URI、Host、参数等必要维度,避免过度隔离导致缓存命中率骤降。
示例配置片段:
proxy_cache_key "$scheme$request_method$host$request_uri$cache_key_suffix";
- 若
$cache_key_suffix为空(如游客未设 device),则退化为普通缓存键,适合通用内容 - 若含
_1001_m,则该键仅被 uid=1001 且 device=mobile 的请求命中 - 不建议直接用完整 Cookie 字符串(长度不可控、含敏感字段、易触发哈希碰撞)
配合 cache_bypass 实现动态绕过策略
除隔离缓存外,还可根据 Cookie 控制是否跳过缓存(例如灰度用户强制回源)。用 map 定义布尔变量,再传给 proxy_cache_bypass。
示例:对含 beta=1 的请求不走缓存
map $http_cookie $cache_bypass {
~*beta=1 1;
default 0;
}
# 在 location 中启用
proxy_cache_bypass $cache_bypass;-
proxy_cache_bypass值非空且非 0 即绕过缓存,无需严格布尔 - 可叠加多个 map 变量(如
$cache_bypass$auth_debug),实现复合条件判断 - 注意:绕过逻辑发生在缓存查找前,不影响已存在的缓存项
验证与调试要点
map 变量本身不可直接 log,需借助 add_header 或 log_format 输出到响应头或日志中,便于确认分流是否生效。
- 在 location 中添加:
add_header X-Cache-Key "$scheme$request_method$host$request_uri$cache_key_suffix"; - 自定义日志格式:
log_format cache_debug '$remote_addr - $upstream_cache_status "$request" "$http_cookie" "$cache_uid" "$cache_device"'; - 检查 Nginx 启动时是否报错:“map: invalid regular expression” 多因括号未转义或语法错误
- Cookie 值含空格、分号、特殊字符时,正则需更宽松(如
~*uid=([^;]+)),但需防范注入风险











