最清晰可控的方式是为不同HTTP状态码单独配置proxy_cache_valid;需按顺序显式声明,200/301/302缓存10m,404缓存30s,5xx缓存10s,any兜底5s,并确保proxy_cache_path、proxy_cache及响应可缓存三者同时满足。

直接为不同 HTTP 状态码写独立的 proxy_cache_valid 指令,是最清晰、最可控的方式。Nginx 会按状态码精确匹配,更具体的规则优先于 any,后出现的同状态码配置还会覆盖前面的——所以顺序和显式性很重要。
按业务语义分组设置常见状态码
不必所有状态码都单独列,可按响应性质归类,兼顾语义与运维习惯:
-
proxy_cache_valid 200 301 302 10m;→ 成功响应和重定向通常稳定,适合中等时长缓存 -
proxy_cache_valid 404 30s;→ 防恶意扫描,缓存“不存在”结果几十秒即可,太长会掩盖新上线资源 -
proxy_cache_valid 500 502 503 504 10s;→ 后端故障类错误,短时缓存缓解雪崩,但需配合proxy_cache_use_stale提升可用性 -
proxy_cache_valid any 5s;→ 兜底策略,确保未显式声明的状态码也有默认缓存期(不会覆盖上面已定义的)
对重定向做精细化区分
301 和 302 语义不同,缓存策略也应分离,不能合并或依赖通配:
-
proxy_cache_valid 301 7d;→ 永久重定向,可长期缓存;浏览器和 CDN 也倾向信任 -
proxy_cache_valid 302 2m;→ 临时重定向,必须设短,避免用户错过上游变更 - 若上游返回的 302 带
Cache-Control: no-cache,需加proxy_ignore_headers Cache-Control;才能让上述规则生效 - 如重定向路径含查询参数(如
/old?ref=a→/new?ref=a),记得用proxy_cache_key $scheme$proxy_host$request_uri;或显式包含$args
确保缓存真正生效的硬性前提
proxy_cache_valid 单独存在是无效的,以下三项必须同时满足:
- 在
http块中定义缓存区:proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g; - 在
location中启用该区:proxy_cache my_cache; - 上游响应本身要“可缓存”:默认不缓存带
Set-Cookie、Cache-Control: private/no-store或Pragma: no-cache的响应;必要时用proxy_ignore_headers Set-Cookie Cache-Control;强制忽略
验证是否按预期工作
调试阶段建议加一行头标识,直观判断缓存行为:
-
add_header X-Cache-Status $upstream_cache_status;→ 响应中会出现HIT、MISS、EXPIRED或BYPASS - 用
curl -I http://host/path多次请求,观察X-Cache-Status变化和响应时间下降 - 注意:浏览器对 301 有强本地缓存,测试时优先用
curl绕过干扰 - 若始终是
MISS,检查proxy_cache_key是否含动态变量(如$cookie_xxx)、是否有Vary头导致 key 分裂











