用map指令在nginx层拦截并重写缓存响应头,按uri路径映射业务类型(如product/user/api/static)及对应max-age,忽略后端cache-control,统一注入新头,结合cache_key后缀隔离存储,并添加x-cache-business头和日志便于观测。

用 map 指令重构后端返回头实现弹性缓存,核心不是修改后端响应体,而是**在 Nginx 层拦截、识别、重写缓存相关响应头**,让不同业务类型(如商品页、用户中心、活动页、API 接口)拥有各自独立的缓存行为。它不依赖后端代码改造,靠请求特征做实时判断,真正实现“业务驱动”的缓存策略。
识别业务类型:用 URI 路径或 Host 做第一层分类
业务类型通常体现在 URL 结构中,比如 /product/、/user/、/api/v2/、/campaign/。在 http 块中定义 map,把路径映射成业务标识和对应缓存时长:
-
~*/product/→"product"和"10m"(商品页缓存 10 分钟,兼顾新鲜与性能) -
~*/user/profile→"user"和"0s"(用户私有数据不缓存) -
~*/api/→"api"和"5s"(接口快速过期,防状态滞留) -
~*/static/或~*\.(js|css|png)$→"static"和"1y"(静态资源长期缓存) - default →
"generic"和"1m"(兜底策略,避免漏配)
覆盖后端 Cache-Control:强制注入 Nginx 级缓存指令
很多后端会自带 Cache-Control,但往往一刀切。要让 map 策略生效,必须绕过它:
- 加
proxy_ignore_headers Cache-Control;,让 Nginx 忽略后端返回的该头 - 统一用
add_header Cache-Control "public, max-age=$cache_max_age" always;注入新策略 -
always参数很关键:确保即使返回 304、404、500,缓存头也存在,避免中间代理或浏览器误判
隔离缓存存储:避免不同业务互相污染
仅控制响应头还不够——如果所有请求都存进同一个 cache zone,商品页更新可能意外击中用户页旧缓存。需配合 proxy_cache_key 引入业务维度:
- 定义另一个 map:
map $business_type $cache_suffix { product "_prod"; user "_user"; api "_api"; static "_static"; default "_gen"; } - 在 location 中设置:
proxy_cache_key "$scheme$request_method$host$request_uri$cache_suffix"; - 这样,
/product/123和/user/profile即使 URI 相似,也会存到完全不同的 key 下
增强兼容性与可观测性
生产环境需要兼顾老浏览器和排障需求:
- 保留
expires $cache_max_age;—— 它会自动生成Expires头,对仍依赖它的 IE 等有效 - 加一行
add_header X-Cache-Business $business_type;,方便通过响应头快速确认当前走的是哪类策略 - 日志中记录
$business_type和$cache_max_age,便于分析缓存命中率按业务分布











