要让 fastcgi_cache_use_stale 真正支撑高可用,必须精准配置 http_500-504 和 timeout 触发条件,确保缓存区已定义、key 稳定、5xx 响应被 fastcgi_cache_valid 缓存,并通过 skip_cache 过滤敏感请求,配合 fastcgi_read_timeout 控制降级时机。

要让 fastcgi_cache_use_stale 在 Nginx 中真正支撑高可用转发,关键不是把它当成“兜底开关”,而是构建一套有明确触发边界、缓存可依赖、请求可隔离的降级链路。它本身不提升后端稳定性,但能让用户在 PHP-FPM 暂时不可用时,看到一个仍可读的旧页面,而非空白或 502 错误。
只启用可信的 stale 触发条件
该指令的作用是:当 Nginx 与 PHP-FPM 通信失败时,若本地存在对应缓存,就返回它——但前提是这个缓存必须真实存在且键稳定。盲目开启所有选项反而会放大风险:
-
必配:
http_500 http_502 http_503 http_504—— 这些是 PHP-FPM 明确返回的错误码,信号清晰、可信度最高 -
推荐加:
timeout—— 对应fastcgi_read_timeout超时,防 PHP 卡死不响应,是缩短等待死区的核心条件 -
慎用:
error—— 仅适用于连接被拒、地址无法解析等底层故障;高并发下易误判,不建议单独启用 -
禁用:
invalid_header—— 此类错误发生在响应头解析阶段,Nginx 直接终止流程,根本不会走到缓存逻辑
确保 stale 有内容可返
stale 不生成缓存,只复用已有内容。如果缓存从未成功写入,或 key 总在变化,stale 就完全失效:
- 在
http{}块中定义缓存区:fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=phpcache:100m inactive=30m use_temp_path=off; - 缓存 key 必须剔除动态字段:
fastcgi_cache_key "$scheme$request_method$host$request_uri";(去掉时间戳、用户 ID、随机参数) -
fastcgi_cache_valid必须覆盖 5xx 响应:fastcgi_cache_valid 500 502 503 504 1m;,否则错误响应根本不进缓存,stale 永远无数据源
跳过不该缓存的请求
若登录页、带参数 URL 或含身份 Cookie 的请求被缓存,stale 会把他人页面或空响应推给用户,造成严重逻辑错误:
- 用变量拦截敏感路径:
if ($request_uri ~* "/wp-admin/|/wp-login.php|/user/") { set $skip_cache 1; } - 跳过带查询参数的请求:
if ($query_string != "") { set $skip_cache 1; } - 识别登录态 Cookie:
if ($http_cookie ~* "wordpress_logged_in|PHPSESSID|auth_token") { set $skip_cache 1; } - 在 location 中绑定:
fastcgi_cache_bypass $skip_cache;和fastcgi_no_cache $skip_cache;
配合超时参数控制等待窗口
用户卡顿多久才触发 stale,由 fastcgi 超时参数决定。设得太长,用户白屏太久;设得太短,健康请求也可能被误判:
-
fastcgi_connect_timeout 3s:建立 TCP 连接超时,判断 PHP-FPM 是否挂死或负载过高 -
fastcgi_send_timeout 5s:发送 FastCGI 请求的上限,防写阻塞 -
fastcgi_read_timeout 8s:最关键——从 PHP-FPM 读取响应的总时长,超时即触发stale timeout











