实现细粒度nginx缓存控制的关键是精准定义缓存边界,需组合proxy_cache、map变量预处理、cache_key定制及响应头策略;按资源类型差异化配置,静态资源长期缓存,动态内容禁用共享缓存或设短时stale;map清洗变量确保cache_key可靠;响应头与权限控制协同拦截。

要实现细粒度的 Nginx 缓存内容控制,关键不在“开不开缓存”,而在于**精准定义缓存边界**——包括缓存谁、缓存什么、缓存多久、缓存给谁看。它需要组合使用 proxy_cache 机制、map 变量预处理、cache_key 定制、以及响应头策略,缺一不可。
按资源类型差异化缓存策略
静态资源(JS/CSS/图片/字体)和动态内容(HTML/API)必须分开对待。Nginx 本身不识别文件用途,需靠 location 匹配 + 指令嵌套来隔离:
- 对
/static/或后缀如.js.css.png的请求,启用长期缓存并设Cache-Control: public, immutable, max-age=31536000 - 对
/api/或index.html这类动态入口,禁用共享缓存(private, no-store),或仅允许短时 stale-if-error - 避免在全局 server 块里统一写
proxy_cache,否则 HTML 和 JS 会共用同一缓存区,导致版本错乱
用 map 构建可信缓存维度变量
直接把 $arg_v 或 $http_user_agent 塞进 proxy_cache_key 是危险的——它们可能为空、被截断、或解析时机不对。正确做法是先用 map 清洗、归一化、兜底:
- 标准化设备类型:
map $http_user_agent $cache_device { ~*mobile|android|iphone mobile; ~*tablet tablet; default desktop; } - 提取并清理版本参数:
map $arg_v $cache_version { "" "v0"; default "$arg_v"; }(空 v 参数转为 v0,避免 key 碎片化) - 所有 map 必须声明在
http{}块顶层,确保请求一进来就完成匹配,不依赖后续阶段
定制 cache_key 实现内容隔离
默认 $scheme$request_method$host$request_uri 不足以区分带不同参数或设备的响应。你需要显式拼接清洗后的变量:
- 示例 key:
proxy_cache_key "$scheme$request_method$host$uri$is_args$args$cache_device$cache_version"; - 务必包含
$args或明确过滤掉无意义参数(如utm_*),否则/page?a=1和/page?a=2可能命中同一缓存 - 不要用
$request_body—— 它不可靠且影响性能;POST 请求一般不应缓存,应由业务层控制
配合响应头与权限控制做最终拦截
缓存只是中间环节,真实内容是否可返回,还需结合响应头和访问控制:
- 后端返回
Cache-Control: private或no-cache时,Nginx 默认不缓存;如需强制缓存,加proxy_ignore_headers Cache-Control;并自行担责 - 敏感接口(如用户中心)可通过 IP 白名单 +
proxy_cache_bypass绕过缓存:proxy_cache_bypass $remote_addr;配合allow/deny控制 - 用
add_header X-Cache-Status $upstream_cache_status;输出命中状态,便于前端或监控识别缓存行为











