nginx可通过fastcgi_cache_use_stale配合timeout参数,在上游超时(如fastcgi_read_timeout)时返回过期缓存,避免用户长时间等待;需配置缓存区域、key、valid、stale条件及cache_lock等基础项才能生效。

当上游服务器(如 PHP-FPM)响应缓慢或暂时不可用时,Nginx 默认会等待直到超时才返回错误。但通过合理配置 fastcgi_cache_use_stale 配合超时参数,可以让 Nginx 在后端“卡住”时,仍返回一个过期缓存版本,避免用户长时间白屏或报错——这就是所谓“缩短等待死区”的核心思路。
理解 fastcgi_cache_use_stale 的作用时机
该指令不是让缓存“永远可用”,而是定义在什么异常情况下允许使用已过期但本地尚存的缓存响应。关键在于:它只在 Nginx 尝试与上游通信失败或超时时触发,而不是在缓存过期时自动生效。
常见可启用 stale 的条件包括:
- error:连接被拒绝、重置或无法解析 upstream
- timeout:fastcgi_read_timeout 或 fastcgi_connect_timeout 触发
- updating:当前缓存正被后台更新,可先返回旧版本
- http_500 / http_503 等:上游明确返回了服务端错误
配合 timeout 参数控制“死区”长度
真正决定用户等待多久的,是 fastcgi_*_timeout 系列参数。它们设得太长,stale 就没机会触发;设得太短,又可能误判健康请求。建议组合如下:
- fastcgi_connect_timeout 3s:建立到 PHP-FPM 的 TCP 连接,超时即认为进程挂死或负载过高
- fastcgi_send_timeout 5s:发送 FastCGI 请求头/体的上限,防写阻塞
-
fastcgi_read_timeout 8s:最关键的参数——从 PHP-FPM 读响应的总时长,超时即触发
stale timeout
只要 fastcgi_read_timeout 触发,且你启用了 fastcgi_cache_use_stale timeout,Nginx 就会跳过等待,直接返回缓存(即使已过期)。
必须搭配的缓存基础配置
stale 不是独立功能,依赖完整缓存链路。漏掉任一环节,stale 就不会生效:
- 开启缓存区域:
fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=fcache:100m inactive=60m; - 绑定缓存到 location:
fastcgi_cache fcache; - 设置缓存键与过期:
fastcgi_cache_key $scheme$request_method$host$request_uri;+fastcgi_cache_valid 200 302 10m; - 启用 stale 条件:
fastcgi_cache_use_stale error timeout updating http_500 http_503; - (可选但推荐)允许过期缓存用于高并发场景:
fastcgi_cache_lock on;+fastcgi_cache_lock_timeout 5s;
验证与调优提示
上线前务必用真实慢响应测试:
- 临时在 PHP 脚本中加
sleep(10)模拟超时,观察是否在 8 秒左右返回旧缓存(HTTP 响应头带X-Cache: HIT from stale类标识) - 检查 Nginx error log,确认出现
upstream timed out并伴随using stale cache日志 - 避免把
fastcgi_read_timeout设得比业务平均耗时低太多,否则健康请求也可能被误判为 timeout - 对登录态、POST、含 Cookie 的请求,默认不缓存,stale 也不起作用——需额外用
fastcgi_cache_bypass和fastcgi_no_cache显式控制










