502 Bad Gateway是Nginx作为网关未能从上游获取合法HTTP响应,问题必在Nginx→upstream链路;须先查error.log定位具体错误(如Connection refused、timed out、Connection reset),再用curl直连上游验证,并检查上游进程、端口监听、系统资源及日志。

502 Bad Gateway 不是 Nginx 挂了,而是它向上游发了请求,但没收到合法 HTTP 响应——问题一定出在 Nginx → upstream 这一段,排查必须从这个链路切入,不能重启糊弄。
看 error.log 里最具体的错误行
这是唯一能告诉你“到底卡在哪一步”的地方。别跳过这步直接改配置。
-
connect() failed (111: Connection refused):上游根本没监听端口,比如php-fpm没启动、gunicorn进程崩了、或proxy_pass写错了地址/端口 -
upstream timed out (110: Connection timed out):Nginx 连上了,但上游迟迟不返回响应头,大概率是上游卡死、OOM、线程池满(如pm.max_children耗尽)或数据库锁死 -
recv() failed (104: Connection reset by peer):上游主动断连,常见于 Flask/FastAPI 未处理异常直接退出、Node.js 未 catch promise rejection、或 TLS 握手失败(如 upstream 返回了 HTTPS 响应但 Nginx 配了 HTTPproxy_pass)
用 curl 绕过 Nginx 直连 upstream
验证是不是 Nginx 的锅:如果直连也失败,那 502 根本和 Nginx 无关。
- 查 upstream 地址和端口:
grep proxy_pass /etc/nginx/conf.d/*.conf,例如得到proxy_pass http://127.0.0.1:8000; - 本地直连测试:
curl -v http://127.0.0.1:8000/health,观察是否返回 200、超时、连接拒绝,或返回非 HTTP 内容(如 Python traceback 文本) - 注意:如果 upstream 绑定的是
127.0.0.1,远程机器的 curl 会失败,必须在 Nginx 所在机器上执行
检查 upstream 进程和资源是否真实就绪
很多“服务在跑”只是假象——进程活着,但已无法处理新请求。
- 确认进程存活:
ps aux | grep gunicorn或systemctl is-active php-fpm,但别只看状态,要结合日志 - 查上游日志关键行:
tail -n 50 /var/log/php-fpm/www-error.log | grep -i "unable\|timeout\|oom\|max_children" - 检查系统级限制:
cat /proc/sys/net/core/somaxconn(影响 TCP backlog)、ulimit -n(影响文件描述符)、ss -s看 ESTAB 连接数是否逼近上限
proxy_read_timeout 和 proxy_connect_timeout 不是万能解药
调大超时参数只能掩盖问题,不能修复根因。尤其在高并发下,盲目加 timeout 可能导致连接堆积、雪崩。
-
proxy_connect_timeout 5:仅控制建立 TCP 连接耗时,对上游处理慢无效 -
proxy_read_timeout 60:控制从 upstream 读响应头+体的总时间,若上游平均响应 5 秒,设成 60 就等于让请求排队等 12 倍时间 - 真正该调的是 upstream 自身:比如 PHP-FPM 的
pm.max_children、Python 应用的 worker 数、数据库连接池大小
最容易被忽略的点:502 日志里出现 Connection reset by peer 时,90% 情况下 upstream 进程已经崩溃或被 OOM killer 杀掉,但 systemd 仍显示 “active (running)”——得去 dmesg -T | grep -i "killed process" 翻内核日志才能确认。


















