nginx 不存在 proxy_cache_revalidate 指令,它是长期误传的伪指令;实际智能缓存更新依赖后端正确返回 etag/last-modified、nginx 内置协商逻辑及合理缓存配置协同实现。

Nginx 本身没有 proxy_cache_revalidate 这个合法指令——它在所有官方文档、源码和稳定版本中均不存在,属于长期误传的“伪指令”。你看到的所谓配置效果,实际来自 Nginx 内置的标准 HTTP 缓存协商逻辑,而非某个开关指令。
真正起作用的是三个环节的配合:后端正确返回 ETag 或 Last-Modified → Nginx 在缓存过期时自动发起 If-None-Match 或 If-Modified-Since 请求 → 后端干净返回 304 Not Modified。只有这个闭环成立,才能复用本地缓存体、只传响应头,从而节省回源带宽。
后端必须生成并响应有效的 ETag
ETag 是内容指纹,不是装饰头:
- 值必须用英文双引号包裹,如 ETag: "a1b2c3"(强校验)或 ETag: W/"x9y8z7"(弱校验)
- 静态资源(.js/.css/.png)由 Nginx 或 Apache 托管时,默认开启 ETag,无需额外操作(除非显式关闭)
- 动态接口(PHP/Node.js/Python)需在响应首次生成时计算内容哈希(如 MD5 或 SHA256),输出 ETag;收到 If-None-Match 后严格比对,一致则返回 304,且响应体必须为空
- 禁止返回 Content-Length: 0、Transfer-Encoding: chunked 或多余头字段,否则 Nginx 可能解析失败而降级为 200
Nginx 端要启用合理缓存策略与保护机制
不靠“伪指令”,靠真实配置支撑协商行为:
- 定义缓存区:proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=1h;
- 在 location 中启用缓存:proxy_cache my_cache;
- 设置明确有效期(让缓存有机会“过期后验证”):proxy_cache_valid 200 302 10m;
- 防并发击穿:proxy_cache_lock on; + proxy_cache_lock_timeout 200ms;
- 提升用户体验:proxy_cache_use_stale updating; + proxy_cache_background_update on;
如何验证条件请求是否真实生效
不能只看配置,要看日志和响应头:
- 在 log_format 中加入 $upstream_cache_status,例如:log_format main '$remote_addr - $upstream_cache_status "$request" $status';
- 访问日志中出现 revalidated,表示缓存已过期、Nginx 发起条件请求并收到 304
- 用 curl -I 观察:首次访问应有 ETag 和 Cache-Control;缓存过期后再次访问,若返回 304 且无 Content-Length,说明协商成功
- 注意区分:客户端主动发的条件请求(如浏览器 F5)也会返回 304,但 $upstream_cache_status 显示为 MISS 或 HIT,不是 revalidated
不复杂但容易忽略:ETag 的价值不在“配什么指令”,而在于后端是否真正把它当成内容指纹来用——配得再全,源站返回 200 或乱生成 ETag,Nginx 就永远发不出有效的 If-None-Match,也收不到 304。











