记一次生产环境Nginx 502 bad gateway问题分析解决过程

问题:胶东移动体验上线部署后,访问web通过nginx访问接口返回502 bad gateway,查看nginx错误日志如下:

2020/04/28 20:24:31 [error] 2056#7704: *430 WSARecv() failed (10054: An existing connection was forcibly closed by the remote host) while reading response header from upstream, client: 10.98.11.10, server: , request: "GET /log-service/log/crash/list?crashStatus=&startTime=1587398400000&endTime=1588089599999&desc=1&page=0&pageSize=10 HTTP/1.0", upstream: "http://10.64.22.21:9999/log-service/log/crash/list?crashStatus=&startTime=1587398400000&endTime=1588089599999&desc=1&page=0&pageSize=10", host: "10.98.11.10:5555", referrer: "http://10.98.11.10/"

根据信息看出问题是,nginx与上游服务器的连接被强行断开,但为什么会被断开呢?

第一反应就是nginx所在dmz去服务器与应用服务器网不同,但是两服务器之间的网络策略都做好了,而且其他接口访问都是正常的,项目经理那边反馈的信息是网都配好了,自己ping 和telnet端口都没问题,便认为不是网络的问题(此处买下的此次不太成功解决问题的伏笔)

通过在网上搜索资料,大多说的都是关于长连接的配置,配了一通没有任何效果后,再思考不用长连接可否,于是将nginx keepalive_timeout 设置成 0,再启动nginx后,发现不止原来的接口仍不好使,现在所有的接口都502了......再看错误日志,现在换成另外一个错了

2020/04/28 22:27:45 [error] 3004#6500: *211 no live upstreams while connecting to upstream, client: 10.98.11.10, server: , request: "GET /zuul/configure-service/config_dict/item/ARTICLE_UUID HTTP/1.0", upstream: "http://nginx_zuul/zuul/configure-service/config_dict/item/ARTICLE_UUID", host: "10.98.11.10:5555", referrer: "http://10.98.11.10/"

也就是nginx请求时,没有找到可用的上游服务器,没啥没有上游服务器呢,nginx上游服务器两台网关服务器,都正常运行,一测都能够走通,这下更是百思不得其解了

不得已再次配置长连接,配置后大部分接口正常了,崩溃日志接口仍然502。

为什么不配置长连接就是找不到上游服务器呢:

查看网关服务器发现大量的端口处在time_wait状态,我们只配了前端-->Nginx的长连接,但是nginx-->API的长连接却没有配置,默认情况下nginx访问后端都是用的短连接,当大量访问产生后,后端服务没有可用端口和nginx连接通信。此处有疑问这种情况往往出现在压测的情况下,而此时系统负载并不太大为啥会出现?

此问题的解决过程,参考下述文章:

https://xiezefan.me/2017/09/27/nginx-502-bug-trace/

https://www.cnblogs.com/zjfjava/p/10909087.html

https://blog.csdn.net/weixin_34220179/article/details/92601408

继续分析通过nginx访问崩溃日志接口502的问题,通过抓包发现:

当nginx所在的服务器(10.98.11.5)向应用服务器(10.64.22.21)发送崩溃日志请求时,21返回的数据包,标识TCP复位,显示21-->5的网络有问题!

关于TCP RST标识:

RST表示复位,用来异常的关闭连接,在TCP的设计中它是不可或缺的。就像上面说的一样,发送RST包关闭连接时,不必等缓冲区的包都发出去(不像上面的FIN包),直接就丢弃缓存区的包发送RST包。而接收端收到RST包后,也不必发送ACK包来确认。

TCP处理程序会在自己认为的异常时刻发送RST包。例如,A向B发起连接,但B之上并未监听相应的端口,这时B操作系统上的TCP处理程序会发RST包。

又比如,AB正常建立连接了,正在通讯时,A向B发送了FIN包要求关连接,B发送ACK后,网断了,A通过若干原因放弃了这个连接(例如进程重启)。网通了后,B又开始发数据包,A收到后表示压力很大,不知道这野连接哪来的,就发了个RST包强制把连接关了,B收到后会出现connect reset by peer错误。

此次解决问题过程可总结两点经验:

1、遇到问题时,先从简显处排查,像这次刚开始就是直接测接口抓包,就不用后来死扣长连接不得其解了

2、生产环境涉及多服务间问题的排查时,抓包工具有很大帮助

文章最后还有一个疑问:为什么其他接口都访问时,5到2021都没问题,只有崩溃日志访问时才有问题,尚待继续研究

猜你喜欢

转载自blog.csdn.net/asde1239/article/details/105855232