Nginx 反向代理报 502,先别急着改配置:按上游存活、配置、日志三步排查
上周帮同事看一个线上故障:页面突然全站 502,重启 Nginx 没用,重启后端也没用,最后发现是后端监听端口改了,Nginx 还在连旧端口。这件事让我把 502 的排查顺序固定下来:先确认上游活着,再看配置,最后才翻日志。顺序反了,很容易在日志里绕圈子。
第一步:上游还活着吗
502 的意思是 Nginx 收到了请求,但从上游拿不到有效响应。最常见的原因不是 Nginx 坏了,而是后端根本没在跑,或者跑着却没监听 Nginx 要连的那个端口。
先看进程在不在:
ps aux | grep -E 'php-fpm|gunicorn|node|java' | grep -v grep
systemctl status php-fpm
进程不存在,或者状态是 failed、inactive,问题基本就在这里:先把后端拉起来,再看它自己的日志找崩溃原因,例如:
journalctl -u php-fpm -n 50 --no-pager
进程在,也别急着放心。再看它到底监听了哪个地址和端口:
ss -tlnp | grep 9000
这里最容易踩的坑有三个:一是后端监听了 9001,Nginx 却连 9000;二是后端只绑了 127.0.0.1,而 Nginx 在另一台机器上;三是进程在,但 CPU 打满、内存打满,实际上已经假死。磁盘满了也会让后端写不了日志和临时文件,顺手看一眼:
df -h
top -bn1 | head -20
第二步:Nginx 到上游通不通
进程和端口都对,还要确认 Nginx 所在机器真的能连上后端。直接在 Nginx 机器上测一次,比看配置管用:
curl -v --connect-timeout 3 http://127.0.0.1:9000/
Connection refused,一般是回到第一步:端口没监听。Connection timed out,多半是防火墙、安全组或者 SELinux 挡住了。云上部署还要多查一步:Nginx 所在安全组的出方向、上游所在安全组的入方向,是不是放行了这个端口。
第三步:配置有没有指错地方
网络通了,再看 Nginx 是不是把请求送错了地方。先把生效配置完整打出来,别只看自己记得的那一段:
nginx -T 2>/dev/null | grep -A 20 'upstream'
nginx -t
重点核对三处:proxy_pass 的地址和端口是不是后端实际监听的那一个;用了域名做上游时,DNS 能不能解析,可以用 nslookup 验证;proxy_read_timeout、proxy_connect_timeout 是不是设得太短,后端只是慢,还没挂,Nginx 等不及就断开了。
还有一种间歇性 502,容易被忽略:后端返回的响应头或响应体太大,proxy_buffer_size、proxy_buffers 设得太小,Nginx 存不下就直接 502。调大缓冲再复现一次,如果故障消失,基本就能定位。
第四步:翻日志,把猜测变成证据
前面三步排除了存活、连通和配置问题,才到日志这一步。Nginx 的 error 日志通常已经把原因写得很直白:
tail -100 /var/log/nginx/error.log
grep 'upstream' /var/log/nginx/error.log | tail -50
几种常见写法对应不同方向:connect() failed (111: Connection refused) 是上游没监听;upstream prematurely closed connection 是上游提前断开了连接,要去查上游日志;upstream timed out 是后端太慢,优先调超时或优化后端,而不是一味重启 Nginx。
access 日志用来判断范围:所有请求都 502,说明上游整体不可用;只有部分请求 502,可能是过载或偶发崩溃;只有某个 URL 才 502,往往是后端处理这个请求时出了问题。
一个能直接用的排查顺序
- ps、ss 确认后端进程和监听端口;
- curl 直连后端,确认网络和安全组放行;
- nginx -T 核对 proxy_pass、upstream、超时和缓冲;
- error 日志定位具体错误,access 日志判断影响范围。
按这个顺序走,大多数 502 不用半小时就能定位到某一层。最怕的是反着来:一上来就改配置、重启服务,故障现象被重启掩盖,根因反而找不到了。先确认后端活着且能连上,再谈配置和日志,这句话记下来,下次遇到 502 能省不少时间。
- 点赞
- 收藏
- 关注作者
评论(0)