排查一个常见 502 现象
现象
nginx 的日志中有两个关键错误
- no live upstreams while connecting to upstream
- upstream prematurely closed connection while reading response header from upstream
排查过程
- 压测 nginx > A ESB / nginx > B ESB,单点链路均无异常
- 压测 nginx > A+B ESB 稳定复现问题,结合 nginx 配置文档、中文博客分享,猜测为 keepalive 配置问题,导致 ‘upstream prematurely closed connection while reading response header from upstream’
- esb 服务实为 uwsgi ,同时观测后端服务的链接情况,发现 TIMEWAIT 数量多(20W+)
1
netstat -nat | grep :8002 | awk '{a[$6]++}END{for(i in a){print i,a[i]}}'
- 观察内核参数,keepalive 相关的参数均为默认值
- nginx http block 中 keepalive 为 60000,此时可以确认 TIMEWAIT 过多原因出现在此,keepalive * worker 就是最终连接数,设置 keepalive 为 65
- 重复压测 nginx > A+B ESB 链路仍稳定出现问题,“upstream prematurely …” 现象降低,但仍有较多 “no live …”,此处分析应为后端服务异常了
- 同时翻查 uwsgi 日志,观察到有热重启发生,伴随有模块加载异常的问题
- nginx upstream 配置 server ip1 max_fails=1 fail_timeout=30s,配合 7 的现象,确认为 upstream server 均不可用导致,临时将 max_fails 设置
为 0,多次复测未复现,问题解决
分析
upstream prematurely closed connection while reading response header from upstream 分析
- nginx 发完请求后连接被”意外”关闭了, 导致读取响应失败,nginx 打印 upstream prematurely closed connection while reading response header from upstream 的日志,此处需要通过抓包确认,猜测某个 upstream 在数据传输等待响应 response 头部过程中主动 RST 了连接(后经排查可知,某个时刻 uwsgi 发生了热重启,可以匹配此行为)
- 分析后端 RST 连接的原因时发现 nginx 上有大量的 TIMEWAIT 连接,通过翻查源码和 nginx 文档后大概确认为配置问题。后端重启,server 收到 ACK 后应该 RST,但终止了连接,导致 TIMEWAIT
no live upstreams 分析
- nginx 中 upstream 默认是轮询的,upstream 中每个 server 组成链表去轮询,若 server1 连接失败后,服务将被移出链表,在 fail_timeout 超时后再次重新加入。
- 当两台 server 均被被移出后,因无 upstream 可用,nginx 打印 no live upstreams 日志,无响应返回 502