一、什么是 502 Bad Gateway?
当 Nginx 作为反向代理服务器时,它本身不直接处理业务逻辑,而是把请求转发给后端服务,例如:
- Node.js 应用
- Next.js 服务
- PM2 管理的进程
- Python / Java / Go 服务
- PHP-FPM
- Docker 容器内服务
如果 Nginx 无法从后端服务拿到正常响应,就会返回:
502 Bad Gateway
通俗理解就是:Nginx 能接到用户请求,但它访问后端服务失败了。
二、最常见的 502 原因
线上最常见的原因基本集中在以下几类:
1. 后端服务根本没启动
例如你的 Node.js 项目没运行,或者 PM2 进程已经挂掉。
2. 代理地址写错了
比如你 Nginx 配的是:
proxy_pass http://127.0.0.1:3000;
但你的项目实际跑在 3001 或者跑在 Docker 容器里。
3. 端口没监听成功
服务虽然看起来启动了,但实际上没有真正监听指定端口。
4. 服务启动后立刻崩溃
Nginx 去请求时,后端已经退出,所以返回 502。
5. Unix Socket 配置错误
例如 Nginx 代理到 socket 文件,但文件不存在或权限不对。
6. 超时或资源不足
后端响应过慢、内存不够、CPU 打满,也可能导致网关错误。
7. 防火墙、SELinux、权限问题
尤其在 Linux 服务器上,权限和系统策略经常是隐藏故障点。
三、先记住一个排查原则
排查 502 时,不要上来就改 Nginx 配置。
正确思路应该是:
- 先确认后端服务是否正常
- 再确认端口或 socket 是否可访问
- 最后再检查 Nginx 配置
也就是:先看后端,后看代理。
这是最省时间的办法。
四、第一步:检查 Nginx 配置是否有语法问题
先确认 Nginx 配置本身没有写错:
nginx -t
如果看到:
syntax is ok
test is successful
说明配置文件语法没问题。
然后重载配置:
systemctl reload nginx
# 或
nginx -s reload
注意:语法没问题,不代表代理就没问题。这一步只是排除低级错误。
五、第二步:查看 Nginx 错误日志
这是定位 502 的核心步骤。
常见日志位置:
tail -f /var/log/nginx/error.log
如果你使用了站点独立日志,也可能在:
tail -f /www/wwwlogs/你的域名.error.log
常见报错示例
1. 连接被拒绝
connect() failed (111: Connection refused) while connecting to upstream
这通常说明:
- 后端服务没启动
- 端口写错
- 服务崩溃了
2. 上游超时
upstream timed out (110: Connection timed out) while reading response header from upstream
这通常说明:
- 后端接口执行太慢
- 数据库查询卡住
- 服务资源不足
- Nginx 超时配置过短
3. 没有这个 socket 文件
connect() to unix:/run/xxx.sock failed (2: No such file or directory)
说明:
- socket 文件不存在
- 后端程序没创建成功
- 路径写错
4. 权限不足
connect() to unix:/run/xxx.sock failed (13: Permission denied)
说明:
- Nginx 没权限访问 socket 文件
- 用户组不一致
- 权限配置错误
六、第三步:直接检查后端服务能不能访问
假设 Nginx 配置是:
location / {
proxy_pass http://127.0.0.1:3000;
}
那么你要直接在服务器上测试:
curl http://127.0.0.1:3000
如果返回正常 HTML、JSON、接口数据,说明后端服务是活的。
如果直接报错:
curl: (7) Failed to connect to 127.0.0.1 port 3000
那问题就不在 Nginx,而在你的后端服务。
这一步非常关键,因为它能瞬间把故障范围缩小一半。
七、第四步:检查端口是否真的在监听
很多人以为服务启动成功了,其实它根本没监听端口。
可以用以下命令检查:
ss -ltnp | grep 3000
# 或
netstat -ltnp | grep 3000
正常情况下会看到类似:
LISTEN 0 511 127.0.0.1:3000
如果没有结果,说明:
- 程序没启动
- 程序启动失败
- 监听的不是这个端口
- 只监听了 IPv6 或其他地址
八、第五步:如果你用的是 PM2,一定检查进程状态
很多 Node.js / Next.js 项目都通过 PM2 部署。
先查看进程:
pm2 list
如果状态不是 online,而是:
- errored
- stopped
- 反复重启
那 502 基本就是它导致的。
查看具体日志:
pm2 logs
# 或查看某个应用
pm2 logs app-name
常见日志问题包括:
- 环境变量缺失
- 端口冲突
- Prisma 数据库连接失败
- 构建产物不存在
- Node 版本不兼容
- 依赖没安装完整
九、一个非常典型的实战案例
场景
你部署了一个 Next.js 项目,Nginx 配置如下:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
访问域名返回 502。
排查步骤
-
先测试 Nginx:
bashnginx -t通过。
-
查看错误日志:
bashtail -f /var/log/nginx/error.log发现:
connect() failed (111: Connection refused) while connecting to upstream -
继续测试后端:
bashcurl http://127.0.0.1:3000连接失败。
-
再看 PM2:
bashpm2 list pm2 logs日志发现:
Error: Could not find a production build in the .next directory
真正原因
项目只执行了:
npm install
pm2 start npm --name app -- start
但没有先构建:
npm run build
修复方式
npm run build
pm2 restart app
恢复正常。
十、Nginx 代理 Node.js / Next.js 的标准配置示例
这是一个比较常用且稳定的配置:
server {
listen 80;
server_name example.com www.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
proxy_read_timeout 60s;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
}
}
十一、几个最容易忽略的坑
1. 服务只监听了 localhost,但容器里访问不到
如果你的服务跑在 Docker 容器中,Nginx 在宿主机,而应用只监听容器内部 127.0.0.1,就会出问题。
这时要确认网络映射和监听地址。
2. Next.js 没有生产构建
开发环境能跑,不代表生产环境能跑。
线上通常要执行:
npm run build
npm run start
而不是直接 npm run dev。
3. 端口被别的程序占用了
如果 3000 端口被占用,你的服务可能启动失败。
检查:
lsof -i :3000
结束占用进程:
kill -9 PID
4. 环境变量缺失
很多项目本地能启动,线上启动失败,原因不是代码,而是:
- .env 没上传
- 数据库地址不对
- API Key 缺失
- Prisma 配置不完整
5. 数据库连接失败导致服务挂掉
Nginx 看到的是 502,但真正原因可能是 Node.js 服务因为数据库连接异常直接退出。
比如:
- PostgreSQL 没启动
- 数据库账号密码错误
- Prisma migration 未执行
- 服务器不能访问数据库地址
十二、如果是超时导致的 502,怎么处理?
如果错误日志里是超时问题,可以从两个方向修复:
方案一:优化后端接口
例如:
- 减少慢查询
- 给数据库加索引
- 避免接口里做重计算
- 减少同步阻塞操作
方案二:适当调大 Nginx 超时参数
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
send_timeout 60s;
如果是特别慢的任务,不建议让 HTTP 请求一直等待。更好的做法是:
- 提交任务
- 后台异步处理
- 前端轮询结果
十三、一套通用的 502 排查命令
下面这组命令,几乎可以应对大多数 502 问题:
# Nginx 相关
nginx -t
systemctl status nginx
tail -f /var/log/nginx/error.log
# 后端服务相关
curl http://127.0.0.1:3000
ss -ltnp | grep 3000
lsof -i :3000
# 进程管理相关
pm2 list
pm2 logs
systemctl status your-app-service
journalctl -u nginx -n 100 --no-pager
如果你是 Node.js 项目,我建议优先看这三项:
- curl 本地端口
- pm2 logs
- nginx error.log
通常 80% 的问题都能很快定位。
十四、线上修复的推荐顺序
真实工作中,我一般按这个顺序处理:
第一步:看 Nginx 错误日志
确认是拒绝连接、超时、权限还是 socket 问题。
第二步:本机 curl 后端
确认后端服务本身是否可访问。
第三步:确认进程是否存活
看 PM2、systemd、Docker 容器状态。
第四步:检查端口和监听地址
防止代理到错误端口。
第五步:检查应用日志
找出真正导致服务挂掉的根因。
第六步:最后才改 Nginx
不要把时间浪费在怀疑 Nginx 上。
十五、如何预防 502 再次发生?
想减少线上 502,建议你做到以下几点:
1. 用 PM2 或 systemd 托管服务
避免应用意外退出后没人拉起。
2. 部署前做健康检查
例如部署脚本里加:
curl http://127.0.0.1:3000
确认服务真的起来了。
3. 保留完整日志
Nginx 日志、应用日志、数据库日志都要能快速查看。
4. 区分开发和生产启动方式
不要把开发命令当生产命令用。
5. 给数据库和外部依赖做容错
避免因为一个依赖挂了,整个服务直接崩掉。
6. 做监控和告警
例如监控:
- 进程存活
- 端口监听
- CPU / 内存
- HTTP 状态码异常比例
十六、总结
Nginx 的 502 Bad Gateway 本质上不是网页打不开这么简单,而是一个非常明确的信号:
代理层能工作,但上游服务没有正常响应。
所以真正高效的排查方式永远是:
- 先看 Nginx 日志
- 再测后端端口
- 再看应用进程和日志
- 最后检查配置
你只要记住一句话:
502 大多数不是 Nginx 挂了,而是 Nginx 后面的服务挂了。
这就是为什么专业运维和程序员在处理 502 时,第一反应永远不是改配置,而是查上游。
问题求助
没能解决你的问题?直接问我
如果你遇到任何技术问题无法解决,可以在这里提交求助。我会尽快查看并回复你。
支持作者
如果这篇文章帮到了你,可以支持我
扫码打赏,支持我持续更新原创排障文章。
