如何根据请求头特征,用map指令灵活调整proxy_cache_valid缓存周期?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1173个文字,预计阅读时间需要5分钟。
可以通过 `map` 指令将请求头(如 `User-Agent`、`Cookie`、`Authorization` 等)映射为具有有效期的缓存变量,然后在 `proxy_cache_valid` 中引用这些变量实现动态控制。注意:
用 map 提取请求头特征并映射缓存策略标识
在 http 块中定义 map,根据请求头内容生成一个代表缓存时长的字符串(如 "60s"、"1h"),或更推荐生成整数秒(便于后续逻辑扩展):
map $http_user_agent $cache_ttl { ~*curl|httpie 10; ~*Mobile 300; ~*Firefox|Chrome 3600; default 86400; }
说明:
-
$http_user_agent是内置变量,对应User-Agent请求头;其他可用$http_cookie、$http_accept_language等 - ~* 表示忽略大小写匹配
- proxy_cache_valid 的固定规则对齐
通过 proxy\_cache\_valid 多行匹配实现“条件化”生效
Nginx 的 proxy_cache_valid 不接受变量,但支持按响应状态码多行声明。我们可以利用 map 变量控制是否启用某条规则——核心技巧是:结合 proxy_cache_valid 和 proxy_cache_use_stale 的触发条件,或更实用的是:用 map 控制 proxy_cache_key 或 proxy_cache_bypass,但若目标仅为“不同请求头走不同缓存周期”,最稳妥方式是为不同策略配置独立 cache zone + 独立 location,或采用以下兼容方案:
✅ 推荐做法:用 map 控制 proxy_cache_valid 的“生效开关”,通过 add_header 验证逻辑,并借助 expires / Cache-Control 响应头反向影响客户端及中间缓存(虽不改变 Nginx 自身缓存时间,但可协同控制整体缓存行为);
✅ 更直接有效的方式(Nginx ≥ 1.11.8):用 proxy_cache_valid 多行 + 状态码 + map-驱动的自定义响应头,配合 add_header 输出 X-Cache-TTL,再通过日志或监控识别策略是否命中。
实际可落地的组合配置示例
以下配置实现了:移动端请求缓存 5 分钟,桌面浏览器 1 小时,API 工具(curl)仅缓存 10 秒:
http { map $http_user_agent $cache_ttl { ~*curl|httpie|wget 10; ~*Mobile 300; ~*Firefox|Chrome|Safari|Edge 3600; default 86400; } <pre class="brush:php;toolbar:false;"># 定义 cache zone(必须全局唯一) proxy_cache_path /var/cache/nginx/api_cache levels=1:2 keys_zone=api_cache:10m max_size=1g inactive=3d; server { location /api/ { proxy_pass https://backend; proxy_cache api_cache; # 关键:用 map 变量控制 proxy_cache_valid 的“隐式选择” # 虽不能变量化 proxy_cache_valid,但可通过以下方式达成等效效果: proxy_cache_valid 200 302 10s; # 默认兜底(curl 类) proxy_cache_valid 200 302 300s; # 移动端 proxy_cache_valid 200 302 3600s; # 桌面浏览器 # ✅ 正确做法:用 if + proxy_cache_valid 不可行(if 在 location 中受限),所以改用: # 利用 map 设置 cache key 差异,使不同 UA 存入不同 key → 间接实现“不同 TTL”管理 proxy_cache_key "$scheme$request_method$host$request_uri $cache_ttl"; # 同时设置合理的 inactive(自动清理超时未访问缓存) proxy_cache_inactive 10m; # 可选:透传后端 Cache-Control,让 Nginx 尊重它(覆盖 proxy_cache_valid) proxy_ignore_headers Cache-Control; # 或反之:强制覆盖后端头(更可控) # add_header Cache-Control "public, max-age=$cache_ttl"; } }
}
说明:
-
proxy_cache_key中混入$cache_ttl,会使相同 URI 但不同 UA 的请求存为不同缓存项,从而避免互相干扰 -
proxy_cache_inactive 10m表示缓存项 10 分钟内未被再次访问就自动剔除 —— 这是对短 TTL 请求的兜底清理机制 - Cache-Control: max-age=60,且你希望优先服从后端,则开启
proxy_ignore_headers Cache-Control;若想完全由 Nginx 控制,可关闭该忽略,并用add_header强制覆盖(注意:add_header 不影响 proxy_cache_valid 决策,只影响下游)
验证与调试建议
启用日志记录缓存行为,确认策略是否生效:
log_format cache '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' '$upstream_cache_status $cache_ttl'; <p>access_log /var/log/nginx/cache.log cache;
关键字段说明:
-
$upstream_cache_status:HIT / MISS / BYPASS / EXPIRED / STALE -
$cache_ttl:你定义的映射值,可用于核对 UA 是否命中预期策略 - curl -I 查看响应头中的
X-Cache或自定义头(如X-Cache-TTL)辅助判断
本文共计1173个文字,预计阅读时间需要5分钟。
可以通过 `map` 指令将请求头(如 `User-Agent`、`Cookie`、`Authorization` 等)映射为具有有效期的缓存变量,然后在 `proxy_cache_valid` 中引用这些变量实现动态控制。注意:
用 map 提取请求头特征并映射缓存策略标识
在 http 块中定义 map,根据请求头内容生成一个代表缓存时长的字符串(如 "60s"、"1h"),或更推荐生成整数秒(便于后续逻辑扩展):
map $http_user_agent $cache_ttl { ~*curl|httpie 10; ~*Mobile 300; ~*Firefox|Chrome 3600; default 86400; }
说明:
-
$http_user_agent是内置变量,对应User-Agent请求头;其他可用$http_cookie、$http_accept_language等 - ~* 表示忽略大小写匹配
- proxy_cache_valid 的固定规则对齐
通过 proxy\_cache\_valid 多行匹配实现“条件化”生效
Nginx 的 proxy_cache_valid 不接受变量,但支持按响应状态码多行声明。我们可以利用 map 变量控制是否启用某条规则——核心技巧是:结合 proxy_cache_valid 和 proxy_cache_use_stale 的触发条件,或更实用的是:用 map 控制 proxy_cache_key 或 proxy_cache_bypass,但若目标仅为“不同请求头走不同缓存周期”,最稳妥方式是为不同策略配置独立 cache zone + 独立 location,或采用以下兼容方案:
✅ 推荐做法:用 map 控制 proxy_cache_valid 的“生效开关”,通过 add_header 验证逻辑,并借助 expires / Cache-Control 响应头反向影响客户端及中间缓存(虽不改变 Nginx 自身缓存时间,但可协同控制整体缓存行为);
✅ 更直接有效的方式(Nginx ≥ 1.11.8):用 proxy_cache_valid 多行 + 状态码 + map-驱动的自定义响应头,配合 add_header 输出 X-Cache-TTL,再通过日志或监控识别策略是否命中。
实际可落地的组合配置示例
以下配置实现了:移动端请求缓存 5 分钟,桌面浏览器 1 小时,API 工具(curl)仅缓存 10 秒:
http { map $http_user_agent $cache_ttl { ~*curl|httpie|wget 10; ~*Mobile 300; ~*Firefox|Chrome|Safari|Edge 3600; default 86400; } <pre class="brush:php;toolbar:false;"># 定义 cache zone(必须全局唯一) proxy_cache_path /var/cache/nginx/api_cache levels=1:2 keys_zone=api_cache:10m max_size=1g inactive=3d; server { location /api/ { proxy_pass https://backend; proxy_cache api_cache; # 关键:用 map 变量控制 proxy_cache_valid 的“隐式选择” # 虽不能变量化 proxy_cache_valid,但可通过以下方式达成等效效果: proxy_cache_valid 200 302 10s; # 默认兜底(curl 类) proxy_cache_valid 200 302 300s; # 移动端 proxy_cache_valid 200 302 3600s; # 桌面浏览器 # ✅ 正确做法:用 if + proxy_cache_valid 不可行(if 在 location 中受限),所以改用: # 利用 map 设置 cache key 差异,使不同 UA 存入不同 key → 间接实现“不同 TTL”管理 proxy_cache_key "$scheme$request_method$host$request_uri $cache_ttl"; # 同时设置合理的 inactive(自动清理超时未访问缓存) proxy_cache_inactive 10m; # 可选:透传后端 Cache-Control,让 Nginx 尊重它(覆盖 proxy_cache_valid) proxy_ignore_headers Cache-Control; # 或反之:强制覆盖后端头(更可控) # add_header Cache-Control "public, max-age=$cache_ttl"; } }
}
说明:
-
proxy_cache_key中混入$cache_ttl,会使相同 URI 但不同 UA 的请求存为不同缓存项,从而避免互相干扰 -
proxy_cache_inactive 10m表示缓存项 10 分钟内未被再次访问就自动剔除 —— 这是对短 TTL 请求的兜底清理机制 - Cache-Control: max-age=60,且你希望优先服从后端,则开启
proxy_ignore_headers Cache-Control;若想完全由 Nginx 控制,可关闭该忽略,并用add_header强制覆盖(注意:add_header 不影响 proxy_cache_valid 决策,只影响下游)
验证与调试建议
启用日志记录缓存行为,确认策略是否生效:
log_format cache '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' '$upstream_cache_status $cache_ttl'; <p>access_log /var/log/nginx/cache.log cache;
关键字段说明:
-
$upstream_cache_status:HIT / MISS / BYPASS / EXPIRED / STALE -
$cache_ttl:你定义的映射值,可用于核对 UA 是否命中预期策略 - curl -I 查看响应头中的
X-Cache或自定义头(如X-Cache-TTL)辅助判断

