Nginx 官方并无 fastcgi_cache_revalidate 指令,该指令属常见误解;实际需通过 fastcgi_cache_use_stale 配合 Last-Modified/ETag 响应头与 if_modified_since/if_none_match 请求头,使 Nginx 自主返回 304 并绕过 PHP。

启用 fastcgi_cache_revalidate 后,Nginx 在缓存过期时不会直接回源,而是向后端发起一个条件请求(带 If-Modified-Since 和/或 If-None-Match),仅当后端返回 304 Not Modified 时复用旧缓存;否则更新缓存并返回新内容。它本质是“按需验证+按需更新”,而非主动刷新。
开启 revalidate 的前提条件
该指令生效依赖几个关键配置,缺一不可:
- 必须启用
fastcgi_cache并设置有效缓存区(如fastcgi_cache my_cache) - 必须设置
fastcgi_cache_valid,定义不同状态码的缓存时间(例如fastcgi_cache_valid 200 302 10m) - 后端(如 PHP-FPM)需正确响应
Last-Modified或ETag头,且支持条件请求处理 - 建议配合
fastcgi_cache_lock避免缓存穿透导致的重复回源
如何正确配置 fastcgi_cache_revalidate
在 location 或 server 块中添加该指令即可启用:
fastcgi_cache_revalidate on;
它默认开启 If-Modified-Since 验证;若后端同时提供 ETag,Nginx 会自动带上 If-None-Match。无需额外配置头字段,但需确保后端返回的 Last-Modified 时间戳准确(建议由应用逻辑生成,而非固定值)。
验证是否生效的实用方法
可通过响应头和日志确认行为是否符合预期:
- 查看响应头:缓存命中时为
HIT;过期后回源时,检查 upstream 请求是否含If-Modified-Since或If-None-Match - 开启
fastcgi_cache_log_format并记录$upstream_http_last_modified和$upstream_http_etag,比对前后请求值 - 用
curl -I多次请求同一资源,观察X-FastCGI-Cache状态变化及Date/Last-Modified是否更新
常见陷阱与注意事项
这个功能看似简单,但容易因细节失效:
- 后端返回
Cache-Control: no-cache或Expires过期时间早于 Nginx 缓存时间,会导致 Nginx 忽略缓存策略,跳过 revalidate - 动态内容未输出
Last-Modified或ETag,Nginx 无法构造条件请求,退化为强制回源 - 使用
fastcgi_ignore_headers屏蔽了Last-Modified或ETag,会使 revalidate 失效 - 缓存锁(
fastcgi_cache_lock)超时太短,可能造成多个并发请求同时回源,削弱 revalidate 效果
不复杂但容易忽略。关键是让 Nginx 和后端在缓存语义上达成一致:后端负责声明“何时变”,Nginx 负责“按需问”。


















