Nginx 502 Bad Gateway 排查实战:PHP-FPM、超时与上游配置一次讲清


Nginx 报 502 Bad Gateway,是所有站长都绕不开的错误。它的含义很明确:Nginx 作为网关,把请求转发给后端(PHP-FPM、Node、Java、另一台 Nginx),但没有拿到合法响应。所以 502 的问题一定在后端,或者 Nginx 与后端的连接上,不在浏览器,也不在 DNS。这篇按“看日志、查进程、对超时、调缓冲”的顺序,把最常见的几类 502 一次讲清。

一、先看 error.log:502 其实分四种

很多人看到 502 就去重启 PHP,其实日志里已经写清楚了原因。打开站点的错误日志:

tail -n 100 /www/wwwlogs/example.com.error.log

常见的关键字对应四类问题:

  • connect() failed (111: Connection refused):后端没监听,PHP-FPM 没启动或者 socket 路径不对。
  • upstream prematurely closed connection:后端进程处理到一半退出,通常是 PHP 崩溃、内存超限或被 kill。
  • recv() failed (104: Connection reset by peer):后端主动断开,常见于后端超时、连接池耗尽。
  • upstream timed out (110: Connection timed out):Nginx 等后端超时,需要对齐超时参数。

先按日志定位类型,再动手,比盲目重启有效得多。

二、PHP-FPM 是否真的在跑

systemctl status php-fpm
ss -lntp | grep -E "9000|php"

如果 FPM 没起来,先看启动失败原因,常见的是配置语法错误、端口被占用、运行用户不存在。如果 FPM 在跑但 Nginx 连不上,重点检查 fastcgi_pass 指向的地址:用 127.0.0.1:9000 还是 unix socket,两边必须一致,socket 文件权限必须是 Nginx 用户可读写。

另外,PHP-FPM 进程池打满也会表现为 502。看 FPM 的慢日志和状态页,确认 pm.max_children 是否够用。一个粗略的估算方式是:max_children 约等于可用内存除以单个 PHP 进程的平均内存。4G 内存、单进程 60M,最多给到 40 左右,留出系统余量。

pm = dynamic
pm.max_children = 40
pm.start_servers = 8
pm.min_spare_servers = 5
pm.max_spare_servers = 15
pm.max_requests = 500

三、把超时参数对齐

502 里最容易被忽略的是超时。Nginx、PHP-FPM、PHP 本身各有一套超时,任何一层先断,都会返回 502 或 504。三个值要满足:Nginx 的 fastcgi_read_timeout 大于等于 FPM 的 request_terminate_timeout,FPM 的大于等于 PHP 的 max_execution_time。

location ~ \.php$ {
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    fastcgi_read_timeout 120s;
    fastcgi_send_timeout 120s;
    fastcgi_connect_timeout 10s;
}

对应 php-fpm.conf 或进程池配置:

request_terminate_timeout = 120s

php.ini:

max_execution_time = 120

如果站点有导出报表、同步大数据这类长任务,不要一味把超时调大,应该改成异步队列,否则一个慢请求就会占住一个 FPM 进程,并发一高就是大面积 502。

四、上传大文件时的 502

上传大文件报 502,通常是请求体超过了 Nginx 限制,或者临时目录不可写。检查这两项:

client_max_body_size 64m;
client_body_temp_path /var/cache/nginx/client_temp;

同时确认 PHP 的 upload_max_filesize、post_max_size 也放开到相同量级,并保证临时目录有足够空间。磁盘满了同样会导致 502,排查时顺手看一眼 df -h。

五、后端是 Node 或 Java 时怎么查

如果 upstream 指向的是 127.0.0.1:3000 这类应用端口,先确认进程和端口:

ss -lntp | grep 3000
curl -I http://127.0.0.1:3000

本机 curl 能通、外网 502,问题在 Nginx 配置;本机也不通,问题在应用本身。Node 应用注意 keepalive 和进程被 OOM kill 的情况,用 dmesg -T | grep -i oom 确认是否被系统杀掉。

upstream 里如果写的是域名,Nginx 只在启动时解析一次,后端 IP 变了就会一直 502。加上 resolver 并配合变量转发,或者直接写内网 IP,能避免这类隐蔽问题。

六、快速恢复与长期监控

线上出问题时,先恢复再分析:重启 FPM、回滚最近一次配置、临时摘掉异常的后端节点。恢复后把 error.log 和 FPM 慢日志留档,确认根因。

长期看,给 502 加监控比事后救火更重要:按分钟统计 error.log 里的 502 数量,连续超过阈值就告警;同时监控 FPM 进程数、内存、磁盘和后端端口存活。把这几项做好,大部分 502 在用户感知之前就能被发现。

七、最后总结

502 不是一种错误,而是一类错误。先读 error.log 分清是连不上、被断开还是超时,再分别处理 FPM 进程、超时参数、请求体限制和后端存活,基本能覆盖九成以上的场景。最忌讳的是不看日志直接重启,重启只能暂时掩盖问题。


手机扫码阅读

微信或手机浏览器扫一扫,随时随地随心阅读与分享

服务器磁盘空间满了怎么办?Linux 大文件定位、日志清理与扩容一次讲清

网站被挂马怎么办?木马查杀、后门清理与安全加固一次讲清

评 论