fastcgi_cache_use_stale 不是自动错误纠正,而是降级策略:当 PHP-FPM 返回 500–504 或超时(fastcgi_read_timeout)时,Nginx 可返回已缓存的过期内容以维持可用性;需配合 cache_path、稳定 cache_key、cache_valid 覆盖 5xx 及 timeout 触发条件。

Nginx 本身不支持对 FastCGI 后端(如 PHP-FPM)返回畸形响应(如非法状态码、乱码 header、空响应等)进行自动剔除。FastCGI 协议层没有健康探测机制,Nginx 无法像 HTTP upstream 那样通过 proxy_next_upstream 或 check 指令主动探测或隔离异常节点。
但你可以通过组合配置实现近似“故障感知 + 请求级降级 + 缓存兜底”,在 PHP-FPM 返回畸形响应时避免用户看到错误、防止 worker 异常,并间接规避问题节点——这不是剔除节点,而是绕过失败、保护服务连续性。
必须启用的 FastCGI 容错基础配置
以下指令缺一不可,否则 fastcgi_cache_use_stale 等策略无效:
-
定义缓存区(确保有地方存 stale 内容)
fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=phpcache:100m inactive=30m use_temp_path=off;
-
绑定缓存并设置稳定 key(避免 key 变动导致缓存失效)
fastcgi_cache phpcache; fastcgi_cache_key "$scheme$request_method$host$request_uri";
-
让错误响应也能进缓存(stale 要有数据源)
fastcgi_cache_valid 200 301 302 10m; fastcgi_cache_valid 500 502 503 504 1m; # 关键:5xx 也要缓存
-
启用 stale 响应触发条件(只响应可验证的失败信号)
fastcgi_cache_use_stale http_500 http_502 http_503 http_504 timeout;
✅
http_500–504:PHP-FPM 明确返回这些状态码时可信度最高
✅timeout:对应fastcgi_read_timeout超时,防脚本卡死无输出
❌ 避免error和invalid_header:前者易误判,后者根本不会走到缓存逻辑 -
控制超时参数,决定用户等待“死区”长度
fastcgi_connect_timeout 3s; fastcgi_send_timeout 5s; fastcgi_read_timeout 8s; # 最关键:超时即触发 stale
如何应对“畸形响应”本身(非标准 5xx)
当 PHP-FPM 返回非法状态码(如 HTTP/1.1 000 OK、HTTP/1.1 999 Unknown)、空响应、或含 \0 / \r\n\r\n 错乱头时:
- Nginx 会记录
upstream sent invalid response或invalid header - 此时
fastcgi_cache_use_stale完全不生效(因未进入缓存流程) - worker 可能卡死、CPU 暴涨,甚至崩溃
✅ 紧急缓解方式(临时保活):
- 在
location中添加:fastcgi_buffering off; # 关闭缓冲,转为流式透传(慎用,仅限 API 场景)
- 同时调大缓冲区(若问题只是 header 过长而非畸形):
fastcgi_buffer_size 8k; fastcgi_buffers 16 8k;
❌ 不能依赖的方案:
-
max_fails/fail_timeout:FastCGI 的fastcgi_pass不支持这些参数(它们只用于proxy_pass) -
upstream块 + 主动健康检查:FastCGI 是本地 socket 或 TCP 连接,不是 upstream server 列表,无法套用 nginx_upstream_check_module
根治路径:从 PHP-FPM 层拦截畸形输出
Nginx 无法修复源头,必须约束后端:
-
PHP 层统一出口拦截:所有
http_response_code()、header('HTTP/1.1 ...')调用前校验状态码范围(100–599) -
禁用手动拼接 Status 行:用框架标准方法(如 Laravel 的
response()->status(500)) -
启动时加载中间件:检测
$_SERVER['SERVER_PROTOCOL']和http_response_code()是否合法 -
加轻量网关前置(如 Envoy):启用 response transformation,将非法响应强制转为
502 Bad Gateway
小结:FastCGI 场景下“自动剔除”的真实含义
- 没有节点级剔除,只有请求级容错:用 stale 缓存顶住 5xx/timeout
- 没有协议层整形,只有缓冲与超时控制降低 worker 风险
- 所有“自动”都依赖 PHP-FPM 主动返回标准信号;它静默崩溃或发乱码,Nginx 无计可施
- 真正可用的防线在 PHP 层 —— 输出即契约,不守约,Nginx 只能兜底,无法纠错
不复杂但容易忽略。


















