502 Bad Gateway 是 Nginx 最常见的错误之一。它表示 Nginx 作为反向代理,没能从后端服务拿到有效响应。排查 502 的关键是分清楚:是后端真的挂了,还是 Nginx 和后端之间的通信出了问题。
502 常见根因分布
| 根因 | 占比 | 排查命令 |
|---|---|---|
| PHP-FPM 进程耗尽 | 约 40% | ps aux | grep php-fpm 看进程数 |
| 上游服务崩溃 | 约 25% | systemctl status php-fpm |
| Nginx 配置错误 | 约 20% | nginx -t 检查配置 |
| 网络/防火墙阻断 | 约 15% | curl 127.0.0.1:9000 测试 |
排查顺序
→
→
→
先看错误日志
Nginx 的错误日志会告诉你 502 的具体原因:
tail -50 /var/log/nginx/error.log
常见报错:
connect() failed (111: Connection refused):后端没在监听connect() to unix:/run/php/php-fpm.sock failed (13: Permission denied):socket 文件权限问题upstream prematurely closed connection:后端进程崩溃或主动断开upstream timed out (110: Connection timed out):后端响应太慢
检查后端服务状态
如果是 PHP 站点:
systemctl status php8.1-fpm
systemctl restart php8.1-fpm
如果是 uWSGI/Python:
systemctl status uwsgi
systemctl status your-app
后端服务没跑起来,Nginx 必然报 502。
检查端口和 socket
Nginx 配置里的 upstream 地址要和后端监听地址一致:
# PHP-FPM TCP
fastcgi_pass 127.0.0.1:9000;
# PHP-FPM Unix socket
fastcgi_pass unix:/run/php/php-fpm.sock;
确认后端实际监听的是哪个:
ss -tlnp | grep 9000
ls -la /run/php/php-fpm.sock
检查 socket 权限
用 Unix socket 时,Nginx worker 进程必须有权限访问 socket 文件:
ls -la /run/php/php-fpm.sock
通常 www-data 需要读写权限。在 php-fpm 池配置里设置:
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
检查 PHP-FPM 子进程是否耗尽
如果流量突增,PHP-FPM 的子进程可能不够用:
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
查看 PHP-FPM 日志有没有 server reached pm.max_children 的警告。
一个真实案例
某天网站突然全站 502。错误日志显示 connect() to unix:/run/php/php-fpm.sock failed (11: Resource temporarily unavailable)。检查发现 PHP-FPM 的 pm.max_children 只有 10,而当时并发有 50+。临时调大 max_children 到 80,重启 PHP-FPM 后恢复。根本原因是一个页面做了慢查询,请求堆积导致子进程被占满。
502 排查流程图
按这个顺序排查:
- Nginx 错误日志定位具体报错
- 检查后端服务是否在运行
- 检查 upstream 地址/端口/socket 是否匹配
- 检查 socket 权限或防火墙
- 检查后端资源是否耗尽(CPU/内存/子进程)
- 检查后端日志找具体错误
更多 Nginx 故障排查,参考 Nginx 502 Bad Gateway 怎么办?原因定位与解决全流程。
常见问题
问:502 和 504 怎么区分?
答:502 是后端没响应或响应无效;504 是后端在响应但太慢,Nginx 等不及超时了。看错误日志里的状态码和 upstream 返回时间。
问:为什么重启 PHP-FPM 就好了?
答:可能是某个请求卡死了子进程,或者内存泄漏导致进程僵死。重启是临时止血,要找到根本原因(慢查询、死循环、内存泄漏)。
问:Nginx 和后端在同一台机器上为什么还会超时?
答:即使同一台机器,Unix socket 也有队列长度限制。如果后端处理不过来,连接会积压在队列里,最终超时。调大 listen.backlog 或改用 TCP 可以缓解。