5 分钟修复 Nginx 502 Bad Gateway
502 Bad Gateway 错误意味着 Nginx 成功接收到客户端请求,但从上游服务器收到了无效响应。简单来说:Nginx 本身没有问题,是它背后转发请求的后端服务挂了、配置错了、或者正在崩溃。
这是最常见的生产环境错误之一,几乎从来不是 Nginx 自身的 bug。真正的源头是上游服务 —— PHP-FPM、Node.js、Python Gunicorn 或其他应用服务器。按照以下五个步骤,在五分钟内定位并修复根本原因。
步骤 1:检查上游进程是否在运行
502 最常见的原因是上游服务直接停了。首先确认服务是否正在运行:
# 对于 PHP-FPM
systemctl status php-fpm
# 对于 Node.js(通过 PM2)
pm2 status
# 对于 Python / Gunicorn
systemctl status gunicorn
# 对于 Ruby / Puma(systemd)
systemctl status puma
找到 Active: active (running) 这一行。如果显示 inactive 或 failed,重启它并检查 502 是否消失:
# 重启上游服务
systemctl restart php-fpm
# 或使用 PM2
pm2 restart all
如果服务重启后立刻又崩溃,查看服务自身的日志(见步骤 3),找出真正的错误原因。
步骤 2:验证 nginx.conf 中的上游配置
如果上游在运行,下一个最可能的原因是 Nginx 期望的地址和上游实际监听的地址不匹配。打开 Nginx 配置文件,找到 proxy_pass 或 upstream 块:
# 在你的 server 块或 upstream 块中
upstream php_backend {
server unix:/run/php/php-fpm.sock;
# 或者
server 127.0.0.1:9000;
}
server {
location ~ \.php$ {
fastcgi_pass php_backend;
# ...
}
}
常见错误:
- Socket 路径错误:
.sock文件路径和上游监听路径不一致。检查 PHP-FPM 池配置中的listen = /run/php/php-fpm.sock。 - 端口错误:上游监听
9001,但 Nginx 发送到9000。 - IPv4 vs IPv6:Nginx 发送到
127.0.0.1:9000,但上游绑定在[::1]:9000,反之亦然。 - 多个 upstream 块名称冲突。
修改后测试并重载 Nginx:
nginx -t # 测试配置语法
nginx -s reload # 不中断连接地重载
步骤 3:查看 Nginx 和上游日志
错误日志几乎总能告诉你问题出在哪里。同时检查 Nginx 和上游服务:
# Nginx 错误日志(排查 502 最有用的信息)
tail -50 /var/log/nginx/error.log
# PHP-FPM 错误日志
tail -50 /var/log/php-fpm/error.log
# 根据你的池配置,也可能是:
tail -50 /var/log/php8.2-fpm/error.log
# Node.js 应用日志
pm2 logs --lines 50
# Gunicorn 日志
journalctl -u gunicorn --no-pager -n 50
关键错误信息:
connect() failed (111: Connection refused)—— 上游没有运行或端口不对。connect() to unix:/run/php/php-fpm.sock failed (13: Permission denied)—— Nginx 无法读取 socket 文件(见步骤 4)。upstream prematurely closed connection—— 上游在处理请求时崩溃了。recv() failed (104: Connection reset by peer)—— 上游强制关闭连接,通常是超时或被 OOM Killer 杀掉。
步骤 4:应用常见修复方案
根据日志输出,选择对应的修复方法:
4a. 重启上游服务
systemctl restart php-fpm
如果服务反复崩溃,检查上游错误日志。常见原因:内存不足(OOM Killer)、PHP 文件损坏、或依赖更新导致不兼容。
4b. 修复 Socket 权限
如果错误日志显示 socket 文件 Permission denied,说明 Nginx(通常以 nginx 或 www-data 用户运行)无法访问它:
# 查看 socket 文件的属主和权限
ls -la /run/php/php-fpm.sock
# PHP-FPM 池配置控制这些设置:
# /etc/php/8.2/fpm/pool.d/www.conf
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
更新池配置后重启 PHP-FPM:
systemctl restart php-fpm
4c. 增大代理缓冲区
有时上游发送的头部或响应体超过 Nginx 默认缓冲区大小,导致 502。在 location、server 或 http 块中添加:
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_read_timeout 300;
然后重载 Nginx:
nginx -s reload
4d. 增大上游超时设置
如果上游响应慢导致 502,调整超时参数:
fastcgi_read_timeout 300;
fastcgi_send_timeout 300;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
步骤 5:验证修复结果
应用修复后,确认 502 已解决:
# 本地快速测试
curl -I http://localhost
# 期望响应:
# HTTP/1.1 200 OK
# Content-Type: text/html; charset=UTF-8
# ...
# 从外部测试(替换为你的域名)
curl -I https://example.com
应该看到 200 OK(或 301/302 重定向),而不是 502 Bad Gateway。同时用浏览器打开网站确认端到端功能正常。
速查表:原因与修复
| 症状 / 日志信息 | 根本原因 | 修复方法 |
|---|---|---|
Connection refused |
上游未运行或端口错误 | 启动上游;验证配置中的端口/socket |
socket Permission denied |
Nginx 用户无法读取 socket 文件 | 设置池配置中的 listen.owner 和 listen.mode |
upstream prematurely closed connection |
上游崩溃(OOM、致命错误) | 查看上游日志;增加内存限制 |
| 仅大页面出现 502 | 代理缓冲区太小 | 增大 proxy_buffer_size 和 proxy_buffers |
| 慢请求出现 502 | 超时 | 增大 fastcgi_read_timeout 或 proxy_read_timeout |
| 服务器重启后出现 502 | 上游服务未设置开机启动 | systemctl enable php-fpm |
进阶提示:如果你使用 Cloudflare 或其他 CDN,浏览器看到 502 但服务器上 curl 正常,502 可能来自 CDN 层。检查 CDN 控制台中的源站连接错误。