首页 > Technology > 正文

Nginx 504 Gateway Timeout 怎么办?超时优化与排查指南

fenij 2026-07-29 10 Technology

网站突然报 504 Gateway Timeout,说明 Nginx 把请求转给了后端(PHP-FPM、Node、Java 等),但后端在限定时间内没给回结果,Nginx 等不及就报了超时。它和 502 不一样:502 是后端”连不上或者直接挂了”,504 是后端”连上了但太慢”。这篇文章从定位到解决,带你完整走一遍。

第一步:确认是谁在超时

先看 Nginx 的错误日志,确认到底超时在哪:

tail -50 /var/log/nginx/error.log

典型日志是 upstream timed out (110: Connection timed out) while reading response header from upstream,说明后端处理太慢。再确认一下后端进程还活着没、负载正不正常:

systemctl status php-fpm
top
uptime

要是 CPU 或负载爆了,问题就在后端性能本身;如果负载正常但个别接口超时,多半是某个慢请求(慢 SQL、外部 API 调用)拖住了。

第二步:找到慢在哪里

PHP 环境下把 PHP-FPM 慢日志打开,它能直接把卡住的函数调用栈打印出来:

# php-fpm.d/www.conf
slowlog = /var/log/php-fpm/slow.log
request_slowlog_timeout = 5s

重启 PHP-FPM 之后复现一下问题,去看 slow.log。常见的根因排个序:慢 SQL 查询(缺索引)、调第三方接口没设超时、循环里处理大批量数据、磁盘 IO 瓶颈。数据库这边也可以把 MySQL 慢查询日志打开一起查:

SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 2;

第三步:合理调大超时参数(应急)

如果某些请求本来就很耗时(比如报表导出、大文件处理),可以针对性地把 Nginx 超时调大,在对应的 location 或 server 块里加:

proxy_connect_timeout 60s;
proxy_send_timeout    120s;
proxy_read_timeout    120s;
# fastcgi 场景(PHP)用:
fastcgi_read_timeout  120s;

同时确认后端自己的执行时间限制也跟上,否则 Nginx 在那等,PHP 却先掐断了:

; php.ini
max_execution_time = 120
; www.conf
request_terminate_timeout = 120s

改完先 nginx -t 检查语法,再 systemctl reload nginx。注意:调大超时只是止血,把全站超时一股脑改成 300 秒,反而会让慢请求堆积、连接耗尽,故障被放大。

第四步:从根上优化,避免复发

长期方案按优先级做这几件事:给慢 SQL 加索引或改写查询;调第三方接口时设 3–5 秒超时并做降级;耗时任务改成异步队列(用户提交后后台跑,前端轮询结果);热点数据加 Redis 缓存;PHP-FPM 按内存合理调 pm.max_children,别让进程排队。这几样做完,绝大多数 504 都会消失。

常见问题

Q1:504 和 502 到底怎么区分处理?
502 优先查后端进程是不是挂了、端口/套接字对没对上;504 优先查后端为什么这么慢。日志里 connect() failed 指向 502,upstream timed out 指向 504。

Q2:只有个别页面 504,其他都正常,怎么办?
基本可以锁定是那个页面的慢逻辑:把 PHP-FPM 慢日志打开复现一次,直接看卡在哪个函数,通常就是慢 SQL 或外部请求。

Q3:用了 CDN(如 Cloudflare)报 504 怎么排查?
先绕开 CDN 直接打源站 IP 测试:源站正常,就是 CDN 回源超时设置的问题;源站也 504,就按本文流程查源站。

如果按上面几步还没解决,欢迎到 fenij.com 本文下方留言,把你的报错日志和环境说一下,我尽量帮你分析。