504 是 nginx 主动断开后端连接所致,需按请求链路逐层排查:查 error.log 中 “upstream timed out” 后的阶段描述定位瓶颈,结合 access.log 确认具体 location 和 upstream 配置,再用 curl 直连验证是否应用层问题。

504 不是 Nginx 崩了,而是它在等后端响应时主动断开了连接。排查核心是搞清:它等谁?等什么?等了多久?谁先卡住?必须沿着请求链路一层层验证,不能只调大超时值掩盖问题。
看 error.log 定位超时发生的具体阶段
Nginx 错误日志里那句 “upstream timed out” 后面跟着的描述,直接指明瓶颈位置:
- while reading response header → 后端已连上、也收了请求,但迟迟不返回响应头(常见于应用处理慢、数据库卡住、外部依赖阻塞)
- while connecting → Nginx 根本连不上上游(后端服务未启动、端口不通、防火墙拦截、DNS 解析失败)
- while sending request → 请求发到一半卡住(网络丢包、缓冲区满、上游接收异常)
别跳过这一步——同一份日志里可能混着不同阶段的超时,要按时间戳和 upstream 地址分开归类。
确认触发 504 的具体 location 和 upstream
同一个 Nginx 实例常有多个 server 和 location,超时参数是局部生效的:
- 查 access.log,用
$request_time和$upstream_response_time字段确认哪条请求返回了 504,再反推它命中了哪个server_name和location - 进对应配置块,检查是否显式设置了
proxy_read_timeout、proxy_connect_timeout等;没设置才用全局默认值(如 60 秒) - 注意区分:用
proxy_pass转发 HTTP 服务,看proxy_*参数;用fastcgi_pass连 PHP-FPM,看fastcgi_*参数,两者互不影响
绕过 Nginx 直连 upstream 验证真实耗时
curl 测试必须模拟完全一致的请求(含 headers、body、method),直连 upstream 地址:
- 如果直连也慢或超时 → 问题在应用层:查应用日志、线程堆栈(如 Java 的
jstack)、慢 SQL、外部 API 超时 - 如果直连快(
- 用
curl -w "@format.txt" -o /dev/null -s http://upstream-url输出详细时间字段(time_connect、time_starttransfer 等),比对各阶段耗时
核对超时参数是否匹配业务实际耗时
超时值不是越大越好,要留出合理缓冲,且上下游需协同:
-
proxy_read_timeout是最关键的,它控制 Nginx 等待上游第一个字节的时间,报表导出、文件上传等场景建议设为 300(5 分钟)或更高 -
proxy_connect_timeout和proxy_send_timeout不应比proxy_read_timeout更短,否则还没开始等响应就断了 - 若用 PHP-FPM,
fastcgi_read_timeout必须 ≥proxy_read_timeout,同时 PHP 的max_execution_time也要同步调高 - 所有 timeout 值建议比后端实测最长耗时多留 5–10 秒,避免抖动导致刚踩线就失败











