nginx缓存分浏览器端(expires/cache-control)和服务端(proxy_cache)两类,不可混用;浏览器缓存需慎配immutable与过期策略,proxy_cache须正确配置路径权限、key、valid规则及差异化映射,清理依赖purge模块或手动删文件。

直接说结论:Nginx缓存分两类,浏览器端用 expires 和 Cache-Control,服务端反向代理缓存必须用 proxy_cache 配合 proxy_cache_path,两者不能混用,也不存在“一个配置通吃”的写法。
浏览器缓存怎么配才不踩坑
这是最常被误用的场景:把 proxy_cache 当成浏览器缓存来用,结果发现 F5 刷新没变化、改了文件用户还是旧版。
-
expires只控制浏览器是否发请求,不涉及 Nginx 本地磁盘存储;它生成的是Expires和Cache-Control: max-age=...响应头 - 静态资源(
.js、.css、.png)建议加immutable:add_header Cache-Control "public, immutable";,避免浏览器在带查询参数时误判为新资源 - 别对
.html或 API 接口路径硬套expires 1y——这类内容变频繁,缓存后用户看不到更新,且无法通过 URL 版本号自动失效 - 如果后端已返回
Cache-Control: no-cache,Nginx 的expires指令会被覆盖(HTTP 协议规定后端响应头优先级更高)
proxy_cache 缓存不生效的典型原因
配置写了、nginx -t 通过、reload 也执行了,但 X-Cache-Status 始终是 MISS,说明根本没进缓存区。
-
proxy_cache_path路径的父目录(如/var/cache/nginx)必须由 Nginx worker 进程有读写权限,常见错误是目录属主为root,而 Nginx 运行用户是www-data或nginx -
proxy_cache_valid只对指定 HTTP 状态码生效,比如写了proxy_cache_valid 200 10m;,但后端返回了200 OK以外的响应(如304 Not Modified),就不会缓存 - 默认情况下,Nginx 不缓存带
Set-Cookie头的响应,也不缓存Authorization请求——这是安全机制,如需缓存需显式加proxy_ignore_headers Set-Cookie;和proxy_cache_use_stale error timeout updating http_500; -
proxy_cache_key若没包含$args,带查询参数的 URL(如/api/user?id=123)会被当成同一缓存项,导致数据错乱
差异化缓存必须靠 map + proxy_cache_valid 组合
想让 /static/ 下的图片缓 30 天、/api/v1/ 下的 JSON 缓 5 分钟、/healthz 完全不缓存?单靠 location 匹配做不到精细控制。
- 先在
http块定义映射:map $request_uri $cache_ttl { ~^/static/ "30d"; ~^/api/v1/ "5m"; ~^/healthz "0s"; default "1m"; } - 再在对应
location中引用:proxy_cache_valid 200 $cache_ttl;(注意:proxy_cache_valid支持变量,但仅限于时间值,不能用于开关缓存) - 不要试图用
if ($request_uri ~ /healthz) { proxy_cache_bypass true; }——if在location内不可靠,且proxy_cache_bypass是布尔判断,不是开关指令 - 若需彻底禁用某路径缓存,用
proxy_cache off;,而不是删掉proxy_cache指令——后者只是不启用,但其他继承配置可能仍生效
缓存清理没有 reload 就生效的魔法
Nginx 自带不提供按 URL 清缓存命令,proxy_cache_purge 是第三方模块,编译时未加入就完全不可用。
- 最稳妥的清理方式是删文件:
rm -rf /var/cache/nginx/*,但会清空全部缓存,影响线上稳定性 -
proxy_cache_purge需要额外配置location ~ /purge(/.*)并设权限控制,否则任意人可清空缓存,存在安全风险 - 更推荐的做法是让缓存自然过期:把
inactive=60m设小一点,配合较短的proxy_cache_valid,避免堆积大量无效缓存 - 注意
proxy_cache_path的max_size是软限制——超过后 Nginx 会异步清理最久未访问的缓存,但磁盘可能短时间内爆满











