proxy_cache_revalidate 通过条件请求实现304复用缓存体以节省响应体带宽,需Nginx启用该指令、源站正确支持ETag并返回304、合理设置缓存有效期及锁机制协同生效。

proxy_cache_revalidate 本身不降低带宽,它只是让 Nginx 在缓存过期后改用条件请求(如带 If-None-Match)去问源站“内容变没”,若源站返回 304 Not Modified,Nginx 就复用本地缓存体、只传响应头——这部分节省的是响应体传输量,而非请求次数或连接开销。真正“显著降低回源带宽”的前提是:源站必须正确支持 ETag,且高频返回 304。
要让这个机制落地生效,需三者闭环:Nginx 主动发条件请求 + 源站干净返回 304 + 缓存生命周期设置合理。
必须启用 proxy_cache_revalidate 并配套基础缓存配置
该指令不能单独起作用,需嵌入完整缓存链路中:
- 在
http或location块中写明:proxy_cache_revalidate on;
- 确保已定义缓存区:
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m inactive=1h max_size=1g;
- 在目标 location 中启用缓存并设有效期:
proxy_cache my_cache; proxy_cache_valid 200 302 10m; # 过期时间决定 revalidate 触发频率
源站必须正确生成并校验 ETag
Nginx 发 If-None-Match 的前提,是原始响应里有合法 ETag 头。常见配置要点:
- 静态文件(.js/.css/.png):Nginx/Apache 默认开启 ETag,无需额外操作(除非显式关闭)
- 动态接口(PHP/Node.js/Python):
- 响应首次生成时,需计算并输出
ETag: "abc123"(建议用内容哈希或最后修改时间戳) - 收到
If-None-Match后,比对值一致则立即返回304 Not Modified -
响应体必须为空,不能含
Content-Length: 0、不能有Transfer-Encoding: chunked,否则 Nginx 可能解析失败而降级为200
- 响应首次生成时,需计算并输出
配合 lock 和 background update 防止并发放大回源
不加锁时,多个请求同时命中过期缓存,会触发多次 If-None-Match 请求,反而增加源站压力:
- 开启验证锁:
proxy_cache_lock on; proxy_cache_lock_timeout 5s;
- 允许前台返回旧缓存、后台异步刷新:
proxy_cache_use_stale updating; proxy_cache_background_update on;
验证是否真走 304 复用
靠 $upstream_cache_status 响应头判断行为,推荐在日志中加入:
log_format cache_log '$remote_addr [$time_local] "$request" $upstream_cache_status $status $upstream_http_etag'; access_log /var/log/nginx/cache.log cache_log;
- 日志中看到
revalidated+304→ 表示成功复用旧缓存体 - 若频繁出现
expired+200→ 源站未返回304,优化失效
不复杂但容易忽略











