502 Bad Gateway、504 Gateway Timeout 这两个错一出来,整个站就废了,但 Nginx 日志又臭又长,找不到头绪。其实只要按一个固定套路查,10 分钟内基本能定位到具体服务。
502 和 504 是不一样的故障
别把它们当一回事:
502 的本质是「Nginx 试图把请求转给上游,但上游没给一个有效响应」,常见:PHP-FPM 进程崩了、socket 路径配错、权限拒绝、OOM Killed。504 的本质是「上游在 proxy_read_timeout 内没干完活」,常见:慢 SQL、上游连接池打满、外部 API 慢、文件 IO 阻塞。
第一步:直连后端做二分
绕过 Nginx,直接 curl 后端端口,10 秒把问题切成两半:
grep -r 'proxy_pass\|upstream' /etc/nginx/conf.d/ | grep -v '#'
拿到后端地址(比如 127.0.0.1:9000 是 PHP-FPM、127.0.0.1:8080 是 Node),直接敲:
curl -I --connect-timeout 5 --max-time 10 http://127.0.0.1:8080
| curl 直连结果 | 结论 | 下一步 |
|---|---|---|
| 返回 200 | 后端没问题 | 回头查 Nginx 配置 |
| Connection refused | 后端进程没起 | systemctl status / 重启 |
| 超时 / 极慢 | 后端卡死 | 查资源 / 慢 SQL |
第二步:盯 Nginx error.log 三个关键词
tail -200 /var/log/nginx/error.log
日志又臭又长,但只看三组关键词就够定性:
| 日志关键词 | 含义 | 下一步 |
|---|---|---|
| Connection refused (111) | 端口没人接 | 重启后端 / 改 fastcgi_pass |
| upstream timed out (110) | 后端太慢 | 调大超时 / 优化 SQL |
| no live upstreams | 后端全军覆没 | 扩容 / 看是不是配错 |
| Permission denied (13) | socket 权限 / SELinux | chown / chmod / setsebool |
注意日志里的 upstream: "http://10.0.1.10:8080/api/report" 这段——它精确告诉你哪个节点哪个接口在出问题,特别是排 504 时这是金子。
第三步:基本盘检查 30 秒
错误发生的那一刻同时跑:
date && uptime && free -h && df -h && df -i && ss -lntp | sed -n '1,12p'
重点:
- 磁盘 / inode 100%:502/504 经常从这开始级联,先腾空间
- swap 用满:物理内存已经吃光,慢下来导致 504
- 端口是否真的在监听:ss -lntp 看有没有 9000 / 8080
第四步:常见修法清单
502 是「连不上」,重点查连接:
- PHP-FPM 没启动:
systemctl status php8.3-fpm看状态 - fastcgi_pass 路径错:
nginx -T | grep fastcgi_pass看实际生效值 - socket 权限错:
ls -l /run/php/php8.3-fpm.sock看属主属组是不是 www-data - 进程被打爆 OOM:dmesg | grep -i oom 看内核日志
504 是「太慢」,重点查超时和队列:
- 调大 Nginx 超时:
proxy_connect_timeout 30s; proxy_read_timeout 90s; proxy_send_timeout 90s; - 调大 PHP-FPM 进程数:pm.max_children 视内存调,512MB 内存建议 8~12
- 查慢 SQL:
SET GLOBAL slow_query_log = 'ON';
不要靠重启掩盖根因
重启 Nginx、PHP-FPM、应用服务有时能恢复,但重启只是把现场清掉,下个高峰期同一原因还会炸。正确做法是这次顺便记下来根因:是不是 PHP-FPM worker 数不够?是不是某个接口慢?是不是磁盘快满了?写到 wiki 里,下次少走弯路。
常见问题
Q:502 经常在高峰期偶发,低谷又正常,怎么定位?
A:高峰期 PHP-FPM worker 打满会触发 502。压测前先把 pm.status_list = /run/php/php-fpm-status.sock 打开,ab 跑的时候用 curl http://127.0.0.1/status 看 active process 是否接近 max_children。
Q:用了 Docker,502 / 504 怎么查?
A:思路完全一样——docker exec -it web sh 进容器,按上面步骤查;或在宿主机用 docker logs web --tail 200 看应用日志。注意容器之间网络是不是通的,docker network inspect 看 IP 段。
Q:重启后马上又 502,是不是没救?
A:八成是「上游没启动完,Nginx 已经接到了请求」。Nginx 默认会把请求打到 upstream 列表第一项,启用了 proxy_next_upstream + proxy_next_upstream_tries 2 可以让第一个挂了自动试下一个。
按「直连后端 → 看 error.log → 检查基本盘 → 修具体环节」这套顺序,502/504 在 10 分钟内基本都能落点。如果还卡在中间,把 error.log 末尾几行 + upstream 配置贴到 fenij.com 留言,我帮你接着查。