Nginx在PHP-FPM异常时返回陈旧缓存的核心是精准配置fastcgi_cache_use_stale,仅信任http_500-504和timeout等明确信号,配合稳定cache_key、覆盖5xx的cache_valid、严格bypass敏感请求及合理超时参数,确保stale有内容可返且安全生效。

让 Nginx 在 PHP-FPM 异常时仍能返回页面,核心不是“强行缓存”,而是用 fastcgi_cache_use_stale 控制什么情况下可以安全复用已过期但尚存的缓存内容。它不解决后端故障,而是把故障影响降到最低——用户看到的不是 502,而是几秒前还能正常访问的页面。
只信任明确的错误信号
PHP-FPM 崩溃不会直接通知 Nginx,Nginx 只能根据通信结果做判断。真正可信的依据是 HTTP 状态码或超时行为,而非进程状态:
-
必配:
fastcgi_cache_use_stale http_500 http_502 http_503 http_504—— 这些是 PHP-FPM 明确出错后返回的响应,最可靠 -
推荐加:
timeout—— 对应fastcgi_read_timeout触发,防脚本卡死无响应 -
慎用:
error仅适用于连接被拒、地址无法解析等底层问题;高并发下易误判,不建议单独启用 -
禁用:
invalid_header—— 此时 Nginx 已终止处理流程,根本不会进入缓存逻辑
缓存必须真实存在且键稳定
stale 不生成新缓存,只复用已有内容。若缓存从未写入,或每次请求 key 都不同,降级就完全失效:
- 在
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必须覆盖错误响应:fastcgi_cache_valid 500 502 503 504 1m;—— 让 5xx 也能进缓存,stale 才有数据源
跳过不该缓存的请求
登录页、搜索结果、带 Cookie 的接口一旦被缓存,stale 就可能把他人页面或空响应推给用户:
- 用变量标记跳过:
set $skip_cache 0; - 拦截敏感路径:
if ($request_uri ~* "/wp-admin/|/wp-login.php|/user/") { set $skip_cache 1; } - 过滤带参数 URL:
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:建立连接超时(建议设为 5–10s) -
fastcgi_send_timeout:发送请求给 PHP-FPM 的超时(建议 ≤30s) -
fastcgi_read_timeout:等待 PHP-FPM 响应的超时(stale 的 timeout 条件即由此触发,建议设为 10–15s)


















