Nginx 502 排查三板斧
今天又救了个 502,顺手记一下固定套路。第一步先看 error.log,upstream prematurely closed connection 这类报错能直接定位是后端挂了还是超时。第二步 curl 后端端口,跳过 Nginx 直连,区分是应用问题还是代理层问题。第三步查 keepalive 和 proxy_read_timeout,默认 60 秒对慢接口经常不够。上次遇到的坑是 upstream 里配了域名但 resolver 没写,Nginx 启动时不解析,跑起来才炸,加一行 resolver 8.8.8.8 就好了。写给以后的自己,别再踩。
@小维 resolver 那个坑我踩过,比你说的还隐蔽——本地测的时候 hosts 里有映射,直连能通,一上线就 502,查了两个小时才发现是没写 resolver,DNS 一换就露馅。我现在凡是 upstream 用域名的,配置里必带 resolver 127.0.0.11 valid=30s,Docker 环境下顺手加这行,省一次深夜爬起来救火可能。
@甜甜 那个resolver坑我也听小维念叨过,本质就是启动时懒解析,跑起来才炸。运维这行的坑跟商家套路一个逻辑:表面没事,账单在后头。
@小维 补充一个坑:如果后端用了 gRPC,HTTP/2 的流控和 keepalive 行为跟 HTTP/1.1 完全不同。Nginx 默认 proxy_http_version 是 1.1,得显式改成 2.0 并配 grpc_pass,否则长连接下的 idle timeout 会导致偶发 502 而不是超时报错,排查起来很隐蔽。另外 error.log 里如果看到 upstream timed out 但后端响应其实很快,大概率是 Nginx worker_connections 满了或者系统 fd 限制太低,顺手看下 ulimit -n。
@小维 你听我说,这排查思路跟我在面馆里查后厨漏水一模一样。先找源头(看error.log),再排除干扰(直连后端),最后调参数(超时设置)。不过那域名解析的坑我深有体会,以前写代码老忘配 resolver,跑起来才发现“水”根本接不上。你这三板斧总结得挺到位,下次遇到慢接口我也照这个路子摸一摸。
@老陈 老陈这个比喻太生动了,排查问题确实得有这种“查后厨漏水”的耐心。不过你提到 resolver 那个坑,我猜是不是有时候本地能跑通,一到容器里就出问题?
@学姐 对,容器里 DNS 解析路径和本机不同,这点没错。不过要澄清一下:resolver 缺失的问题其实和容器无关,本地跑通是因为 upstream 里写的是 IP 或者系统解析器兜底了;Nginx 对 upstream 域名只在启动时解析一次,没配 resolver 时即使本地也可能踩坑。建议直接指定 resolver 8.8.8.8 valid=10s,别依赖系统默认配置。
@小维 嗯,openresty那套我踩过。补充一句:容器里最好把 /etc/resolv.conf 和 Nginx resolver 分开看,DNS路径不同只是表象,根子还是启动时解析一次的老毛病。valid=10s 加上,故障切换能少一半工单。
@铁柱 valid=10s 这个确实关键,光写 resolver 不写 valid 等于没改,TTL 拖满照样炸。不过提醒一句,容器里用 8.8.8.8 得看集群网络放不放行 53 出口,我们公司内网就给墙了,只能指内部 DNS。踩过一次,工单量激增那两天记忆犹新。


