Nginx 504 Gateway Timeout 是服务器问题吗?别急着升级,先把这几层查清楚

很多站长一看到网站打开提示 “504 Gateway Timeout”,第一反应就是:服务器是不是不行了?是不是 CPU 不够?是不是要升级香港服务器?
但从我实际处理网站故障的经验来看,Nginx 504 不一定是服务器硬件问题。它更准确的意思是:Nginx 作为网关或反向代理,在规定时间内没有等到后端服务响应。
也就是说,Nginx 本身还能工作,端口也可能正常,但它后面的 PHP、Java、Node.js、Python、数据库、接口服务、缓存服务,或者某个上游代理没有及时返回结果,最后 Nginx 只能给用户返回 504。
一、先说结论:504 是“后端响应超时”,不等于服务器宕机
Nginx 504 Gateway Timeout 常见在这些架构里:
用户浏览器
↓
CDN / Cloudflare
↓
Nginx
↓
PHP-FPM / Node.js / Java / Python / 后端 API
↓
MySQL / Redis / 第三方接口 / 文件存储
当用户访问页面时,Nginx 会把请求转发给后端程序。如果后端处理太慢,超过 Nginx 设置的等待时间,就会出现 504。
比如:
Nginx 等 PHP-FPM 返回结果,等了 60 秒还没回来
Nginx 等后端 Node.js 接口返回,等了 90 秒还没结果
Nginx 代理到另一台服务器,但对方网络或程序卡住
这时用户看到的是 504,但真正的问题可能在:
- PHP-FPM 进程不够;
- MySQL 慢查询卡住;
- 后端程序死循环;
- Redis 连接异常;
- 上游接口太慢;
- 磁盘 IO 被打满;
- 服务器负载高;
- 带宽不是瓶颈,但业务处理链路太慢。
所以,504 不是一句“服务器问题”就能概括的,它是一个链路问题。
二、504 和 502、503 有什么区别?
很多用户会把 502、503、504 混在一起,其实排查方向不一样。
| 错误码 | 通俗理解 | 常见原因 |
|---|---|---|
| 502 Bad Gateway | 后端返回了异常响应,或者连接不上 | PHP-FPM 挂了、端口错了、后端进程崩溃 |
| 503 Service Unavailable | 服务暂时不可用 | 维护、限流、进程满载、服务不可用 |
| 504 Gateway Timeout | 后端太久没响应 | 慢查询、程序卡住、上游接口慢、进程排队 |
简单说:
502 更像是“后端坏了或连不上”
503 更像是“后端暂时不接客”
504 更像是“后端处理太慢,Nginx 等不下去了”
所以遇到 504,不能只看 Nginx,也不能只看带宽,要顺着请求链路往后查。
三、哪些业务最容易出现 Nginx 504?
在香港服务器或海外服务器上,我见过比较容易触发 504 的业务主要有这几类。
1. WordPress / WooCommerce 网站
常见原因:
- 插件太多;
- 后台执行导入、采集、同步;
- WooCommerce 订单查询慢;
- wp-cron.php 被频繁触发;
- 数据库 wp_options 表膨胀;
- 页面未缓存,每次都动态生成。
比如一个 WordPress 外贸站,首页看起来只是普通页面,但实际加载时可能会执行:
主题函数
插件钩子
商品查询
文章查询
评论统计
会员状态判断
远程接口请求
任何一环慢了,都可能让 PHP 执行时间超过 Nginx 的等待时间。
2. 跨境电商后台和 ERP 接口
这类业务经常会调用外部接口,比如:
- 支付接口;
- 物流接口;
- 库存同步接口;
- 第三方 ERP;
- 海外仓接口;
- Shopify / Amazon / TikTok Shop API。
如果接口响应时间从 2 秒变成 30 秒,前端用户可能就直接看到 504。
这时候不是香港服务器带宽不够,而是后端业务依赖链路太长。
3. 图片站、下载站、短视频站
这类网站容易在磁盘 IO 和后端处理上出问题。
比如:
- 图片实时压缩;
- 视频实时转码;
- 文件权限校验;
- 下载链接动态生成;
- 大文件通过 PHP 中转下载;
- 后台批量生成缩略图。
如果所有请求都走后端程序,而不是让 Nginx 直接处理静态文件,就很容易出现 504。
4. Java / Node.js / Python API 服务
API 服务出现 504,常见原因包括:
- 后端线程池耗尽;
- 数据库连接池打满;
- 接口中调用了慢服务;
- 代码里没有合理超时;
- 单个请求占用时间太长;
- 反向代理 timeout 设置过短。
比如 Nginx 代理到本地 Node.js:
location /api/ {
proxy_pass http://127.0.0.1:3000;
}
如果 Node.js 某个接口卡住 60 秒,Nginx 就可能返回 504。
四、先别急着改 Nginx timeout,第一步要看日志
很多人遇到 504 后,第一件事就是改:
proxy_read_timeout 300;
fastcgi_read_timeout 300;
这不是不能改,但如果问题根源是数据库慢查询、PHP 卡死、接口阻塞,只是把超时时间从 60 秒改到 300 秒,用户可能只是从“等 60 秒报错”变成“等 300 秒报错”。
正确做法是先看日志。
1. 查看 Nginx 错误日志
常见路径:
tail -f /var/log/nginx/error.log
如果是宝塔面板,一般可以在:
网站设置 → 日志
或服务器路径中查看对应站点日志。
重点看是否有类似内容:
upstream timed out (110: Connection timed out) while reading response header from upstream
这句话非常关键,意思是:
Nginx 已经把请求转给后端了,
但在读取后端响应头的时候超时了。
如果日志里出现:
connect() failed
那偏向后端服务连接不上。
如果出现:
upstream prematurely closed connection
那可能是后端进程提前断开、崩溃或被系统杀掉。
2. 查看访问日志,找出哪个 URL 超时
可以用:
tail -f /var/log/nginx/access.log
更建议在 Nginx 日志格式里加上请求耗时,例如:
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" '
'request_time=$request_time '
'upstream_response_time=$upstream_response_time';
这样你就能看到:
request_time=65.231 upstream_response_time=65.230
如果某个接口经常超过 60 秒,那基本就能定位到业务 URL。
例如:
/wp-admin/admin-ajax.php
/api/order/sync
/product/export
/video/convert
/user/report/download
这种 URL 如果频繁超时,问题就不在 Nginx,而在后端业务逻辑。
五、服务器资源怎么查?不要只看 CPU
504 不一定是 CPU 高,也可能是内存、磁盘 IO、连接数或进程池排队。
1. 查看 CPU、内存、负载
top
或:
htop
重点看:
load average
CPU us / sy / wa
内存剩余
swap 是否大量使用
如果 CPU 不高,但 load 很高,要特别关注 wa,也就是 IO wait。
2. 查看磁盘 IO
iostat -x 1
如果看到:
%util 接近 100%
await 很高
说明磁盘响应很慢。很多网站 504 的根源并不是 CPU,而是数据库或日志写入把磁盘 IO 拖慢了。
这类情况在机械硬盘服务器、老旧 SATA SSD、日志量很大的站点上比较明显。
所以做数据库、电商、图片处理业务时,我更建议使用 NVMe SSD。
3. 查看网络连接数
ss -s
查看具体端口连接:
ss -antp | grep :80
ss -antp | grep :443
ss -antp | grep :9000
如果 PHP-FPM 使用 9000 端口,可以看是否存在大量连接堆积。
4. 查看 PHP-FPM 是否满了
如果是 PHP 网站,重点看 PHP-FPM 日志:
tail -f /var/log/php-fpm/error.log
或不同系统路径:
tail -f /var/log/php8.1-fpm.log
tail -f /var/log/php7.4-fpm.log
如果看到:
server reached pm.max_children setting
意思是 PHP-FPM 子进程已经用满,新的请求只能排队,排队时间长了就会 504。
这类问题在 WordPress、Discuz、Magento、Laravel 项目里很常见。
六、Nginx 504 常见原因和解决方案
原因一:PHP-FPM 进程数太少
如果服务器是 8 核 16G,但 PHP-FPM 只配置了 20 个子进程,高峰期请求一多,很容易排队。
可以检查 PHP-FPM 配置:
vim /etc/php/8.1/fpm/pool.d/www.conf
常见参数:
pm = dynamic
pm.max_children = 80
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 30
pm.max_requests = 1000
request_terminate_timeout = 120
参考建议:
| 服务器内存 | PHP-FPM max_children 建议 |
|---|---|
| 4G | 20 - 40 |
| 8G | 40 - 80 |
| 16G | 80 - 150 |
| 32G | 150 - 300 |
但这里不能死套,要根据单个 PHP 进程实际占用内存计算。
比如:
ps -ylC php-fpm --sort:rss
如果单个 PHP-FPM 进程平均占用 80MB,服务器预留系统、MySQL、Redis 后还有 8GB 可用,那么:
8192MB ÷ 80MB ≈ 102
这时 pm.max_children 设置 80 - 100 比较合理。
原因二:MySQL 慢查询拖住后端
很多 504 最后都能查到数据库。
比如:
商品列表页打开慢
后台订单导出超时
用户中心加载慢
搜索接口卡住
可以开启 MySQL 慢查询日志:
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 2;
查看慢查询日志:
tail -f /var/log/mysql/mysql-slow.log
重点关注:
Query_time
Rows_examined
Rows_sent
如果一个查询扫描了几十万行甚至几百万行,就要优化索引。
比如订单表:
SELECT * FROM orders WHERE user_id = 10086 ORDER BY created_at DESC LIMIT 20;
建议建立联合索引:
CREATE INDEX idx_user_created ON orders(user_id, created_at);
如果只是简单把 Nginx timeout 调大,数据库慢查询依然存在,高峰期只会把更多 PHP 进程拖死。
原因三:后端接口没有设置超时
很多程序员写接口时会调用第三方 API,但没有设置请求超时。
例如 PHP 里请求远程接口:
$response = file_get_contents("https://api.example.com/check");
如果对方接口卡住,PHP 请求也会跟着卡住。
更合理的做法是设置连接超时和读取超时,例如使用 curl:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.example.com/check");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
curl_setopt($ch, CURLOPT_TIMEOUT, 8);
$response = curl_exec($ch);
curl_close($ch);
这样第三方接口慢,不会把整个站点拖死。
原因四:大任务不应该同步执行
比如这些操作:
批量导出订单
批量生成缩略图
视频转码
邮件群发
数据采集
ERP 库存同步
大文件压缩
AI 推理任务
如果直接在用户请求里执行,很容易 504。
错误做法:
用户点击按钮 → PHP 开始导出 30 万条数据 → Nginx 等待 → 60 秒超时
正确做法:
用户点击按钮 → 创建任务 → 放入队列 → 后台慢慢执行 → 前端轮询进度 → 完成后下载
可以使用:
- Redis Queue;
- RabbitMQ;
- Laravel Queue;
- Celery;
- Supervisor;
- systemd 定时任务;
- Cron 后台任务。
这类改造比单纯升级服务器更有效。
原因五:Nginx timeout 配置太短
如果后端确实需要较长处理时间,比如后台导出、内部管理接口,可以适当增加 Nginx 超时时间。
反向代理场景:
location /api/ {
proxy_pass http://127.0.0.1:3000;
proxy_connect_timeout 10s;
proxy_send_timeout 60s;
proxy_read_timeout 120s;
}
PHP-FPM 场景:
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_connect_timeout 10s;
fastcgi_send_timeout 60s;
fastcgi_read_timeout 120s;
}
但我一般不建议一上来就设置成 600 秒、900 秒。因为这样会让问题隐藏得更深。
比较合理的策略是:
普通页面:30 - 60 秒
后台导出:120 - 300 秒
内部任务接口:单独 location 配置
前台用户访问页面:尽量控制在 1 - 3 秒内响应
七、不同服务器配置下,504 的处理思路不一样
很多用户问:504 是不是该升级服务器?我的看法是:要先看瓶颈在哪里,再决定升 CPU、内存、硬盘还是带宽。
下面用几个香港服务器配置举例。
配置一:入门型香港服务器
适合小型企业站、WordPress 展示站、轻量后台。
CPU:Intel Xeon E3 / E-2334 级别
内存:16GB DDR4
硬盘:480GB SSD / 960GB SSD
带宽:100M BGP,含 25M CN2 直连
系统:Ubuntu 22.04 / CentOS 7.x
适合:企业官网、外贸展示站、小型 WordPress
这类配置如果出现 504,优先查:
WordPress 插件
PHP-FPM max_children
MySQL 慢查询
是否开启页面缓存
是否有异常爬虫
不一定马上换机器。很多小站 504 是插件、数据库或缓存问题。
配置二:高性能香港服务器
适合跨境电商、会员系统、接口站、图片站。
CPU:AMD EPYC 4585PX,16核32线程
内存:64GB DDR5
硬盘:960GB NVMe PCIe Gen4 SSD
带宽:100M BGP,含 25M CN2 直连
系统:Ubuntu 22.04 / Debian 12
适合:WordPress + WooCommerce、Laravel、API 服务、企业后台
这类配置 CPU 单核和多核都比较强,如果还频繁 504,就要重点查:
数据库索引是否合理
PHP-FPM 是否被打满
Redis 是否正常
后台任务是否同步执行
是否存在大量慢接口
磁盘 IO 是否异常
对于 WooCommerce、Laravel、ThinkPHP、Java API 这类业务,64GB 内存可以给 MySQL、Redis、PHP-FPM 留出更大的空间,比 16GB 配置稳定很多。
配置三:数据库 / 高并发型香港服务器
适合数据库独立部署、订单系统、数据量较大的业务。
CPU:AMD EPYC 7402P,24核48线程
内存:128GB DDR4
硬盘:2 × 1.92TB NVMe SSD
带宽:100M BGP / 可升级 1G 国际带宽
系统:Ubuntu 22.04 / Rocky Linux 9
适合:MySQL 独立服务器、ERP、订单系统、日志分析、内部 API
如果数据库压力大,建议把架构拆成:
Web 服务器:Nginx + PHP-FPM / Java / Node.js
数据库服务器:MySQL / MariaDB / PostgreSQL
缓存服务器:Redis
这样 504 的排查会更清晰,也能避免 Web 和 MySQL 抢 CPU、内存、磁盘 IO。
配置四:视频 / 图片处理型香港 GPU 服务器
适合短视频、图片处理、AI 推理、转码业务。
CPU:2 × AMD EPYC 7303
内存:64GB DDR4
硬盘:960GB NVMe PCIe Gen4 SSD
显卡:RTX 4090 / RTX 5090 / A100 可选
带宽:100Mbps 混合带宽,含 25Mbps CN2
系统:Ubuntu 22.04
适合:视频转码、AI 推理、图片识别、模型接口
这类业务最容易因为“同步执行重任务”导致 504。
比如:
用户上传视频 → 服务器马上转码 → 浏览器等待 → Nginx 504
正确架构应该是:
上传文件 → 返回任务 ID → 后台队列转码 → 前端查询进度 → 完成后播放
GPU 服务器不是让用户请求一直等 GPU 算完,而是要配合任务队列使用。
八、推荐的 Nginx + PHP-FPM 优化配置
下面给一个适合 WordPress / PHP 网站的参考方向。
Nginx 站点配置示例
server {
listen 80;
server_name example.com;
root /www/wwwroot/example.com;
index index.php index.html;
client_max_body_size 100m;
keepalive_timeout 30;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_connect_timeout 10s;
fastcgi_send_timeout 60s;
fastcgi_read_timeout 120s;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
}
location ~* \.(jpg|jpeg|png|gif|css|js|ico|webp|svg|woff2)$ {
expires 30d;
access_log off;
}
}
这里重点不是无限拉长超时,而是:
静态资源交给 Nginx 直接处理
PHP 请求才交给 PHP-FPM
适当增加 fastcgi_read_timeout
合理设置 buffer
PHP-FPM 配置示例
假设服务器为:
CPU:16核32线程
内存:64GB
业务:WordPress + WooCommerce
可以参考:
pm = dynamic
pm.max_children = 120
pm.start_servers = 20
pm.min_spare_servers = 20
pm.max_spare_servers = 40
pm.max_requests = 1000
request_terminate_timeout = 120
同时开启慢日志:
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/www-slow.log
这样哪个 PHP 脚本执行慢,就可以通过 slowlog 追踪。
九、MySQL 优化不能忽略,否则 Nginx 怎么调都没用
很多用户调了 Nginx、调了 PHP-FPM,504 还是反复出现,最后发现 MySQL 才是根源。
1. 开启慢查询日志
slow_query_log = 1
long_query_time = 2
slow_query_log_file = /var/log/mysql/mysql-slow.log
2. 检查是否缺少索引
常见问题:
订单表按用户 ID 查询没有索引
文章表按分类查询没有索引
商品表按状态筛选没有索引
日志表数据量太大没有归档
3. 分离大表和日志表
对于电商和 API 业务,日志表、访问记录表、订单流水表不能无限增长。
建议:
访问日志定期归档
订单流水按月份分表或归档
后台报表异步生成
搜索功能交给 Elasticsearch / Meilisearch
热点数据放 Redis
否则服务器配置再高,也可能被几条慢 SQL 拖垮。
十、如果用了 CDN 或 Cloudflare,也可能看到 504
如果网站前面套了 CDN,用户看到的 504 可能来自两种情况:
CDN 等源站超时
Nginx 等后端超时
排查时要分清楚:
1. 直接访问源站 IP 测试
可以临时绑定 hosts:
源站IP example.com
然后绕过 CDN 访问网站。
如果绕过 CDN 仍然 504,说明问题在源站。
如果绕过 CDN 正常,而 CDN 访问 504,可能是:
CDN 到源站线路不稳定
CDN 回源超时太短
源站防火墙拦截 CDN IP
SSL 回源配置异常
源站响应头太慢
十一、什么时候才需要升级服务器?
出现 504 后,不是不能升级服务器,而是要看是否满足这些条件。
适合升级服务器的情况
如果你看到:
CPU 长时间 90% 以上
内存长期不足并大量使用 swap
磁盘 IO util 接近 100%
MySQL 占用资源过高
PHP-FPM 进程长期打满
高峰期连接数明显超过当前配置承载能力
这时候升级服务器是有意义的。
比如从:
4核8G SSD
升级到:
AMD EPYC 4585PX 16核32线程
64GB DDR5
960GB NVMe PCIe Gen4 SSD
100M BGP + 25M CN2
对 PHP 动态处理、数据库查询、后台任务并发都会有明显改善。
不适合只靠升级解决的情况
如果问题是:
SQL 没索引
插件写得差
接口没有超时
任务同步执行
PHP 代码死循环
第三方 API 慢
Nginx 配置错误
那升级服务器只能暂时缓解,不能根治。
比如一个慢 SQL 原来执行 80 秒,换更强服务器后可能变成 30 秒,看起来好了,但高峰期请求一多,还是会 504。
十二、我建议的标准排查流程
遇到 Nginx 504,可以按这个顺序查:
第一步:看 Nginx error.log,确认是否 upstream timed out
第二步:看 access.log,找出具体超时 URL
第三步:看 PHP-FPM / Java / Node.js 后端日志
第四步:看 CPU、内存、load、IO wait
第五步:看 MySQL 慢查询日志
第六步:看是否有第三方接口、远程 API、文件存储超时
第七步:优化程序、SQL、队列、缓存
第八步:最后再调整 Nginx timeout 和升级服务器
不要一上来就改:
fastcgi_read_timeout 600;
proxy_read_timeout 600;
这只能让问题晚一点暴露。
十三、不同业务的处理建议
WordPress 网站
建议:
开启页面缓存
减少重型插件
禁用不必要的 wp-cron
优化 wp_options 表
PHP-FPM 开启 slowlog
MySQL 开启慢查询
图片交给对象存储或 CDN
服务器建议:
16核32线程 CPU
32GB - 64GB 内存
NVMe SSD
100M BGP + 25M CN2
适合外贸站、企业站、WooCommerce 商城。
电商 / ERP / 后台系统
建议:
订单导出异步化
库存同步队列化
接口设置超时
数据库加索引
Redis 缓存热点数据
Web 和数据库分离
服务器建议:
Web:AMD EPYC 4585PX / 64GB / NVMe
DB:AMD EPYC 7402P / 128GB / 双 NVMe
带宽:100M BGP 起步,可按业务升级
视频 / 图片处理业务
建议:
上传和处理分离
转码任务放队列
缩略图后台生成
静态资源走 Nginx 或对象存储
避免 PHP 中转大文件
服务器建议:
CPU:双路 AMD EPYC
内存:64GB 起步
硬盘:NVMe SSD
显卡:RTX 4090 / A100 按任务选择
带宽:按分发需求选择 100M、1G 或更高
十四、504 不一定是服务器差,而是链路里有地方“等太久”
Nginx 504 Gateway Timeout 的本质不是“网站打不开”这么简单,而是:
Nginx 正常收到请求
也正常转发给后端
但后端没有在规定时间内返回结果
所以它可能是服务器资源问题,也可能是程序、数据库、接口、队列、缓存、CDN 回源等问题。
我的建议是:
小站先查插件、PHP-FPM、MySQL 慢查询;
电商站重点查订单、库存、接口和数据库;
图片视频站重点查 IO、转码和任务队列;
API 服务重点查连接池、线程池和超时控制;
高并发业务再结合服务器硬件升级。
如果服务器本身配置偏低,比如 2核4G、4核8G,还要跑 WordPress、电商、数据库、缓存和后台任务,那遇到 504 很正常。
但如果已经是香港高性能物理服务器,比如 AMD EPYC 4585PX / 64GB 内存 / NVMe SSD / 100M BGP + 25M CN2,仍然频繁 504,就更应该深入检查程序和数据库,而不是只盯着带宽或 Nginx 配置。
一句话概括:
504 不是让你马上升级服务器,而是提醒你:Nginx 后面的某个环节已经慢到让用户等不下去了。