“upstream timed out”不是故障原因,而是Nginx在某个环节等不到上游响应后给出的结果;排查必须结合错误后缀(如while connecting/reading等)、$upstream_connect_time与$upstream_header_time耗时、$upstream_status重试序列及access_log中$request_time与$upstream_response_time对比,并通过nc、ss、tcpdump等工具实测验证链路与参数是否生效。

“upstream timed out”不是故障原因,而是Nginx在某个环节等不到上游响应后给出的结果。排查必须结合错误后缀、耗时字段、状态码序列和链路验证,不能只调大超时值。
看括号里的后缀,锁定超时发生阶段
错误日志中括号内的补充说明直接指向问题环节:
-
while connecting to upstream:建连失败。检查PHP-FPM是否运行、socket文件权限、listen.backlog是否溢出(
ss -lnt | grep :9000中Recv-Q ≥ Send-Q)、防火墙或路由不通; -
while reading response header from upstream:连接已建立,但迟迟收不到响应头。重点查后端业务卡点(慢SQL、锁等待、同步调用阻塞),同时确认
fastcgi_read_timeout或proxy_read_timeout是否过小; - upstream prematurely closed connection:连接被后端主动关闭。常见于PHP-FPM ondemand模式回收空闲进程、Spring Boot默认60s idle timeout与Nginx keepalive不匹配。
对比$request_time与$upstream_response_time
通过access log中的两个关键变量判断延迟归属:
- 若
$request_time远大于$upstream_response_time(如8s vs 0.3s),延迟主要在Nginx侧——检查rewrite规则、缓冲区、gzip压缩或SSL握手开销; - 若两者接近且都偏高(如都>3s),问题在后端整体处理能力,需查CPU、内存、线程池、数据库连接池是否打满;
- 配合
$upstream_connect_time和$upstream_header_time进一步分离:前者高→网络或接入层问题;后者高→业务逻辑阻塞。
查$upstream_status序列,识别重试行为
这个字段记录每次尝试的真实状态码,比单个504更有诊断价值:
- 字段为空或仅单个200,但error.log仍有 sporadic “upstream timed out” → 首次请求即失败,未触发重试,倾向偶发网络问题(SYN重传失败、中间设备丢包);
- 高频出现“504,504,200”或“502,504,200” →
proxy_next_upstream生效并兜底,说明后端不稳定:可能是某台实例局部过载,也可能是网络抖动导致部分连接重置; - 频繁出现“502”+“504”组合 → 后端主动关闭了Nginx认为“可用”的空闲连接,需核对keepalive timeout与后端空闲关闭策略是否对齐。
验证链路与参数是否真正生效
别依赖理论配置,要实测验证:
- 用
nc -zv 127.0.0.1 9000或curl -v http://127.0.0.1:9000直连测试端口通断,比ping更真实; - 用
ss -tn state established | grep :9000观察ESTAB连接数是否稳定,确认keepalive是否真正复用; - 启用PHP-FPM慢日志,定位具体哪行代码拖慢响应;
- 抓包验证:用
tcpdump -i any port 9000 -w debug.pcap分析SYN/ACK是否延迟、RST是否突增。


















