当用户访问网站时,如果页面加载很久之后浏览器返回一个504 Gateway Timeout页面,通常意味着Nginx作为反向代理,在等待后端服务(比如PHP-FPM、Tomcat、上游API服务)响应时超过了设定的时间上限,主动切断了连接。这个错误和502 Bad Gateway不同:502一般是后端进程崩溃或拒绝连接,而504是后端还活着,只是处理得太慢,Nginx等不及了。要解决它,不能只是简单把超时时间调大,更需要弄清楚到底是哪个环节慢、哪个参数在起作用。

一、504产生的原理和关键超时参数
Nginx处理代理请求时,与后端之间涉及三个阶段:建立连接、发送请求、等待响应。每个阶段都有独立的超时指令控制,理解这一点是配置的基础。
最常用的是proxy_read_timeout,它定义Nginx从后端读取响应时,两次成功读操作之间的最大等待时间。默认值只有60秒,也就是说如果后端60秒内没有返回任何数据,Nginx就会返回504。注意这里不是整个请求的总时长,而是两次读操作之间的间隔,如果后端持续有数据流回,即使总耗时很长也不会触发超时。
proxy_connect_timeout控制Nginx与后端建立TCP连接的超时,通常几秒就够,一般不建议设置太长,因为连接建立慢往往说明后端有问题,快速失败反而更好。proxy_send_timeout则是Nginx向后端发送请求体的超时,同样指的是两次写操作之间的间隔。这三个参数可以配置在http、server、location三个层级,通常建议只针对慢接口所在的location单独配置。
# 针对慢接口的location单独调整超时
location /api/report/ {
proxy_pass http://backend_server;
proxy_connect_timeout 10s;
proxy_send_timeout 120s;
proxy_read_timeout 300s;
}上面的配置把读超时放宽到300秒,适用于报表导出这类确实耗时的任务。但要强调一句,如果普通页面接口也要跑几十秒才能响应,正确做法是优化后端代码或异步化处理,而不是一味放宽Nginx的限制。
二、FastCGI场景下的超时配置
如果Nginx后面接的是PHP-FPM,走的是FastCGI协议而不是HTTP代理,那么proxy_*系列参数是不生效的,必须使用对应的fastcgi_*参数。这是很多人踩过的坑:改了半天proxy_read_timeout,504依旧出现,就是因为请求实际走的是fastcgi通道。
FastCGI场景下对应的是fastcgi_connect_timeout、fastcgi_send_timeout和fastcgi_read_timeout,默认值同样是60秒。对于WordPress这类执行时间可能较长的PHP应用,可以参照下面的方式调整:
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_connect_timeout 10s;
fastcgi_send_timeout 120s;
fastcgi_read_timeout 300s;
}除了Nginx这一层,PHP自身也有执行时间限制。php.ini中的max_execution_time默认是30秒,PHP-FPM的配置文件里还有request_terminate_timeout,超过这个时间FPM会直接杀掉worker进程。所以完整链路上的限制是取最小值生效的:Nginx的fastcgi_read_timeout、PHP的max_execution_time、FPM的request_terminate_timeout,三者必须同时放宽,缺一个都还是会超时。这一点经常被忽略,也是排查时最容易出问题的地方。
三、504的系统性排查思路
遇到504时,建议按顺序检查三个方面,而不是直接改配置。第一步看Nginx错误日志,路径通常在/var/log/nginx/error.log,日志中会明确写出是upstream timed out还是其他原因,并且能看到具体卡在哪个上游地址。
第二步确认后端是否真的慢。可以在后端服务器上通过curl直接请求对应接口,绕过Nginx测一次响应时间。如果后端本身就要跑两三分钟,那调Nginx超时只是治标;如果后端很快,那问题可能出在Nginx与后端之间的网络,或者是负载均衡把请求打到了一台异常的机器上。
第三步区分超时类型。如果日志里出现的是upstream timed out (110: Connection timed out) while connecting to upstream,说明TCP连接都没建立成功,多半是后端挂了、端口没监听或者防火墙拦截,这时应该调高connect_timeout或者直接修复后端;而如果是while reading response header from upstream,才是真正的响应超时,调整read_timeout才有意义。
另外还有一种常见场景:Nginx前面还有一层CDN或云负载均衡。比如某些云厂商的负载均衡默认90秒就会断开连接,即使你把Nginx超时调成600秒也没用,因为最外层的设备先超时了。排查时要沿着整条链路从外到内逐层核对超时设置,确保外层的等待时间大于内层的处理时间。
四、根治之道:异步化而非无限加时
把超时从60秒调到300秒,本质上是把问题往后推。真正健壮的做法是让慢任务脱离HTTP请求的生命周期:客户端发起任务后立刻返回一个任务ID,后端通过消息队列在后台处理,前端轮询或用WebSocket获取结果。这样每个HTTP请求都能在几秒内响应,504自然消失,用户体验也更好。
总结一下配置层面的要点:HTTP代理场景用proxy_read_timeout,FastCGI场景用fastcgi_read_timeout,同时记得同步调整PHP的max_execution_time和FPM的request_terminate_timeout,并检查外层CDN或负载均衡的限制。而对于确实耗时的业务逻辑,异步化才是根本解决方案。修改任何配置后记得用nginx -t检查语法再执行nginx -s reload平滑生效。
Nginx 504Gateway Timeout超时配置修改时间:2026-09-05 17:24:48