proxy_cache_valid指令用于按HTTP状态码精细化设置反向代理缓存时长,支持多级配置优先级、需配合proxy_cache_path和proxy_cache启用,并依赖proxy_ignore_headers等指令规避后端缓存头干扰。

Nginx 的 proxy_cache_valid 指令是控制反向代理缓存生命周期的核心配置,它允许你为不同 HTTP 状态码设置差异化、精细化的缓存时间,避免“一刀切”式缓存带来的数据陈旧或后端压力问题。
下面从实际配置逻辑出发,讲清楚怎么用、为什么这么用、哪些细节容易踩坑。
按状态码分组设置缓存时长
proxy_cache_valid 支持将多个状态码归为一组,统一指定有效期。语法是:
proxy_cache_valid 200 301 302 10m; proxy_cache_valid 404 1m; proxy_cache_valid 500 502 503 504 30s;
- 每条指令可包含任意数量的状态码(包括
any通配),后面紧跟一个时间值(如10s、5m、1d) - 多条指令可共存,Nginx 会优先匹配最精确的一条(比如同时定义了
200 10m和any 1m,返回 200 时就用 10m,不走any) -
any是兜底规则,仅在没有更具体的匹配时生效
常见组合建议:
-
✅ 推荐:
200 206 304缓存较长时间(如1h或1d) —— 这些是正常响应或协商成功,内容稳定 -
✅ 推荐:
301 302缓存10m–1h—— 重定向目标一般不会秒变,但也不宜过久(避免跳转链失效后仍缓存) -
✅ 推荐:
404缓存10s–1m—— 防止爬虫反复刷不存在路径压垮后端,但太长会掩盖真实修复 -
✅ 推荐:
5xx错误缓存10s–1m—— 给后端留出恢复窗口,避免雪崩;但别设成5m以上,否则用户会长时间看到错误页
作用域层级影响最终行为
proxy_cache_valid 可出现在 http、server、location 三个层级,越靠近请求位置的配置优先级越高,会覆盖上级设置。
例如:
http {
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
}
server {
location /api/ {
proxy_cache_valid 200 5m; # ← 覆盖 http 块中的 200 10m
proxy_cache_valid 500 502 10s; # ← 新增错误码短缓存
}
}
这种结构很实用:
- 全局设宽松基础策略(
http块) - 在关键接口路径(如
/api/)收紧200缓存时间,适配高频更新场景 - 对
/health或/status类探测接口,甚至可以proxy_cache_valid any 0s彻底禁用缓存
配合其他指令才能真正生效
proxy_cache_valid 不是孤立工作的,必须和以下指令协同:
-
proxy_cache_path:必须提前定义缓存区(keys_zone名称要和proxy_cache一致) -
proxy_cache:在location中启用对应缓存区,否则proxy_cache_valid不起作用 -
proxy_ignore_headers:若后端返回了Cache-Control: no-cache或max-age=0,Nginx 默认会跳过缓存;需显式加proxy_ignore_headers Cache-Control;才能强制按proxy_cache_valid执行 -
add_header X-Cache $upstream_cache_status;:加上这句,响应头里会出现HIT/MISS/BYPASS,方便验证是否真按预期缓存
几个典型配置片段参考
静态资源(CSS/JS/图片)缓存:
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
proxy_pass http://backend;
proxy_cache static_cache;
proxy_cache_valid 200 206 301 302 304 7d;
proxy_cache_valid 404 1m;
expires 7d;
}
API 接口缓存(强调时效性):
location /api/v1/ {
proxy_pass http://api_backend;
proxy_cache api_cache;
proxy_cache_valid 200 302 60s; # 数据最多新鲜 1 分钟
proxy_cache_valid 404 30s;
proxy_cache_valid 500 502 503 504 10s;
proxy_cache_use_stale error timeout updating;
}
基本上就这些。关键是理解:缓存不是越长越好,而是根据状态码语义+业务容忍度来定;配置不在多,在准。











