504 Gateway Timeout 是 Nginx 等待后端响应超时主动断连,非自身宕机;应按场景(如上传、报表)在 location 级别调大 proxy_read_timeout,同步调整 fastcgi_read_timeout(PHP 场景)及 PHP 层配置,并确保所有 timeout 均比后端短 5–10 秒。

504 Gateway Timeout 不是 Nginx 本身挂了,而是它等不及后端响应,主动断开了连接。调大超时参数能快速缓解,但盲目加到 3600s 反而可能让问题更隐蔽、更难定位。
proxy_read_timeout 是最常要改的参数
这个值控制 Nginx 等待后端返回第一个字节的最长时间,也是 504 出现频率最高的触发点。默认 60s 对普通 API 完全够用,但遇到文件上传、报表导出、长轮询或跨机房调用时,很容易踩中。
- 先确认你的真实场景:是用户上传大文件?还是后端在查一个没索引的数据库表?别一上来就全局改
proxy_read_timeout - 推荐按 location 精细控制,比如只对 /upload 和 /report 路径延长:
location /upload {<br> proxy_pass http://backend;<br> proxy_read_timeout 1200;<br>} - 不要设成 0(禁用超时),Nginx 会一直挂着连接,最终耗尽 worker_connections
- 注意单位:配置里写
proxy_read_timeout 1200就是 1200 秒,不用加s;但写proxy_read_timeout 1200s也合法
fastcgi_read_timeout 必须同步调整(PHP 场景)
如果你用的是 PHP-FPM,Nginx 和 PHP 之间走的是 FastCGI 协议,proxy_* 系列参数完全不生效。真正起作用的是 fastcgi_read_timeout,它和 proxy_read_timeout 是两套独立逻辑。
- 检查你的
location ~ \.php$块里有没有这行:fastcgi_read_timeout 300; - 同时必须确认 PHP 层没卡住:修改
/etc/php/*/fpm/php.ini中的max_execution_time = 300,并重启php-fpm - 常见陷阱:只改了 Nginx 的
fastcgi_read_timeout,但忘了改php-fpm.conf里的request_terminate_timeout,后者优先级更高
proxy_connect_timeout 和 proxy_send_timeout 容易被忽略
这两个值影响的是“连接建立”和“发请求过去”两个前置阶段,不是等响应。当后端部署在高延迟网络(比如跨云厂商)、或启动慢(Java 应用冷启动)、或用了 TLS 握手耗时长的服务时,它们也可能成为瓶颈。
-
proxy_connect_timeout默认 60s,对跨机房部署建议设为180;如果后端服务启动要 90 秒,那这个值至少得 >90 -
proxy_send_timeout控制 Nginx 向后端发送完整请求体的超时,上传大文件时若网络抖动,它可能比proxy_read_timeout更早触发 - 它们和
proxy_read_timeout没有继承关系,必须显式配置,否则就用默认值
别跳过 upstream 的健康检查和重试机制
单纯拉长超时,只是把问题从“立刻报错”变成“慢得让人崩溃”。真正的稳定性来自快速失败 + 优雅降级。
- 加上
proxy_next_upstream error timeout http_504;,让 Nginx 在超时后自动换一台后端重试 - 配合
proxy_next_upstream_tries 2;,避免单点故障直接打穿 - 记得在
upstream块里配max_fails=3 fail_timeout=30s;,否则健康检查形同虚设 - 最关键的一点:所有 timeout 值都要比后端服务自身的超时短 5–10 秒,否则 Nginx 会在后端已放弃时还在傻等
超时配置不是越大越好,它本质是在“用户体验”和“系统资源水位”之间做权衡。一个没索引的 MySQL 查询拖了 90 秒,你把 proxy_read_timeout 改成 120s,只会让更多请求排队堵死连接池——这时候该修 SQL,而不是改 Nginx。


















