要让nginx在php异常时返回陈旧缓存,需构建“存得住、算得稳、进得去、判得准”闭环:启用fastcgi_cache_use_stale http_500-504,配合fastcgi_cache_path、稳定fastcgi_cache_key、fastcgi_cache_valid覆盖5xx、fastcgi_cache_background_update与fastcgi_cache_bypass过滤敏感请求,并通过x-cache: stale、响应体一致性及毫秒级耗时验证生效。

要让 Nginx 在 PHP 异常时自动返回陈旧缓存,不能只写 fastcgi_cache_use_stale 就完事。它依赖一套协同生效的配置闭环:缓存得存得住、键得算得稳、过期响应得进得去、触发条件得判得准——缺一不可。
精准启用真正反映 PHP 崩溃的触发条件
PHP-FPM 出错最可信的表现是返回明确的 5xx 状态码(如 500、502、503、504),而不是连接失败或超时这类瞬时异常。盲目加 error 或 timeout 会导致缓存被错误复用,掩盖真实问题。
- 推荐写法:
fastcgi_cache_use_stale http_500 http_502 http_503 http_504; - 如需后台静默刷新新内容,可额外加上
updating,但必须同步开启:fastcgi_cache_background_update on; - 避免使用
fastcgi_cache_use_stale error timeout—— 这类条件易误判,尤其在高并发下可能放大雪崩风险
确保缓存“存在且稳定”,stale 才有内容可返
stale 不是生成缓存,只是复用已存在但过期的内容。如果缓存压根没存进去,或 key 总在变,stale 就无从谈起。
- 在
http块中定义缓存区:fastcgi_cache_path /www/server/nginx/fastcgi_cache levels=1:2 keys_zone=phpcache:100m inactive=30m use_temp_path=off; - 缓存 key 必须稳定,禁用时间戳、用户 ID、随机参数等动态字段:
fastcgi_cache_key "$scheme$request_method$host$request_uri"; -
fastcgi_cache_valid必须覆盖错误响应:fastcgi_cache_valid 200 301 302 10m; fastcgi_cache_valid 500 502 503 504 1m;—— 若 5xx 不进缓存,stale 就永远没数据可用
跳过干扰项:防止登录态、参数页、Cookie 冲突缓存
未过滤的动态请求会污染缓存,导致用户看到他人内容,或 stale 返回空页/报错页。关键在于提前拦截不该缓存的请求。
- 用变量控制跳过逻辑:
set $skip_cache 0; - 匹配常见敏感路径:
if ($request_uri ~* "/wp-admin/|/wp-login.php|/admin/") { set $skip_cache 1; } - 过滤带查询参数的请求:
if ($query_string != "") { set $skip_cache 1; } - 拦截含登录 Cookie 的请求:
if ($http_cookie ~* "wordpress_logged_in|comment_author|wp-postpass") { set $skip_cache 1; } - 关联到缓存指令:
fastcgi_cache_bypass $skip_cache; fastcgi_no_cache $skip_cache;
验证是否真起作用,不靠猜,看三件事
停掉 PHP-FPM 后,从客户端发起请求,确认以下三点同时成立,才算容灾链路打通:
- 响应头中出现
X-Cache: STALE(需提前配置:add_header X-Cache $upstream_cache_status;) - 响应体与故障前完全一致,不是 Nginx 默认 502 页面,也不是空 JSON 或乱码
- 响应耗时极低(通常 20–80ms),说明确实绕过了回源,未等待 PHP 超时
这套机制不保证数据最新,但能守住服务可用底线。只要缓存存在、key 稳定、5xx 可缓、stale 触发精准,PHP 故障时用户就几乎感知不到中断。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











