通过nginx转发后应用偶发502bad gateway
序言学习了一些东西,如何才是真正自己能用的呢?好像就是看自己的潜意识的反应,例如解决了一个问题,那么下次再碰到类似的问题,能直接下意识的去找到对应的信息,从而解决,而不是和第一次碰到一样,从头开始查一遍,如果是,那么这个问题对于你来说,可能依旧是一个新的问题。背景:把一个应用从一个代理迁移到nginx的时候,发现应用偶尔会出现502的响应,导致收到告警,而在原来中,是没有502的,...
序言
学习了一些东西,如何才是真正自己能用的呢?好像就是看自己的潜意识的反应,例如解决了一个问题,那么下次再碰到类似的问题,能直接下意识的去找到对应的信息,从而解决,而不是和第一次碰到一样,从头开始查一遍,如果是,那么这个问题对于你来说,可能依旧是一个新的问题。
背景:把一个应用从一个代理迁移到nginx的时候,发现应用偶尔会出现502的响应,导致收到告警,而在原来中,是没有502的,而且时间上没有规律,数量也比较少。
应用偶发502的排查
1 查看nginx日志
nginx只是一个代理,你来什么我就转发什么,出现报错的时候,第一时间就是查看access log和error log,看是否能看到蛛丝马迹。
在accss log中,可以看到客户端请求的时间很短,基本上是几毫秒就完成了请求,也就是request time很短,而且502的响应码是upstream status返回的,一般我们看到这种的时候,我们基本就会认定是后端服务的问题,例如后端的cpu/内存有压力导致,但是因为是迁移过来的,在原来的上面没有此种情况,从而开始进一步排查。
对比正常的请求,发现qps不高的时候大概只有几十的时候更加容易发生,在acess log中不同的地方就是502的响应中,upstream_header_time的时间为空,而upsteam_response_time为0.001秒或者更短,而且出现502之后,没有找下一台服务器,从而可以认为此时nginx和后端服务已经建立了连接,并且传输了数据,正常的200响应中,upstrem_header_time都是有的,另外一个不一样的就是502响应中body_byte_sent都是一个固定值229,这个地方比较迷惑的地方是,不要认为这是发送给后端服务的body大小,而是nginx发送给客户端的body大小,nginx的变量命名都是站在nginx本身来说的,所以sent表示是发送给客户端的大小。
根据access log能得到有用的信息是,和后端服务已经建立连接,但是读取头没读取到,从而导致出现502bad gateway。
查看error log,根据access log找到对应的时间点,能看到具体的报错信息:
upstream prematurely closed connection while reading response
header from upstream
或者是如下的报错信息:
Connection reset by peer) while reading response header
from upstream
从而大致可以判断为,是nginx的配置中的长连接参数导致连接被上游关闭,从而导致响应失败,返回502.
2 修改长连接超时参数
在nginx的默认配置中keepalive_timeout为60秒,当和后端的连接如果超过了60秒,那么nginx会回收这个链接,再创建新的连接使用。
对比迁移前的代理,查看其中配置的超时时间为20秒,从而将超时时间修改为20秒,然后再次切换到nginx中,观察半小时后,发现还是有502的响应,询问应用的研发,后端框架的超时时间是多久,说是20秒,发现这个时间时间可能不对,从而进行抓包查看。
在容器中抓包比较麻烦,容器不能装tcpdump,只能到容器所在的物理机上面的网络命名空间去抓包,从而使用nsenter进入命名空间抓包,因为这个是偶发,所以抓包的时间比较长,导致这个包会很大。
抓包之后,使用wireshark打开,在502的包前面,服务端的确发送了一个reset包,重置了连接。(在此需要注意,分析包的时候,你会发现nginx和客户端是正常的握手挥手关闭连接,不要纠结为啥正常的关闭连接了,还能收到502响应)
在对reset包进行查看tcp流的时候,查看这个链接的存活时间,发现只有5秒,而查看其他正常响应的时间,也是5秒,说明后端的框架中设置的长连接时间为5秒。
继续修改长连接参数为4秒,为什么不设置为5秒,因为也有可能那么巧合。。。可以看到reset包之前的包,nginx已经向后端服务发送了请求包,但是后端服务先发了一个fin包,然后再发送了reset包,从而导致请求发送了,但是服务端重置了连接。如果两者的时间相同,那么会在极其巧合的时间内导致502,如果应用的qps比较高,也不会产生502,因为连接被快速关闭了。
长连接的时间改的很短,造成的影响是如果qps高,会频繁的进行创建连接,销毁连接,影响性能。
至此,问题解决,从而也可以发现对于长连接来说,只要超时时间到了,一定会被回收,而不管是否还有数据在传输。另外,把nginx的时间设置成小于后端服务,也让nginx掌握控制权,进行连接的管理。超时回收连接的好处就是可以节省系统资源,不然会导致很多的连接无法关闭。
当出现问题的时候,如何发现问题:靠告警
当出现问题的时候,如何去解决:日志,监控
当出现网络问题的时候,用什么工具:tcpdump,wireshark,netstat,ss
风言风语
一个正常,一个不正常,这种排查就很麻烦,虽然有对比的数据,但是总体的排查还是比较麻烦的,而且是偶发,偶发的问题总是比直接坏了的情况更加复杂。
当一开始已经判定是这个参数的时候,就会去修改这个参数,但是实际上修改成多少,那就不好猜了,最终的定论只能通过抓包来看,不是必现的问题,抓包都要抓上几个小时,枯燥乏味的事情。
当排查一个问题的时候,如果百思不得其解,那么说明。。。有些基础的概念你不懂,要不然的话,应该很快能猜到可能出现问题的地方。
AI有决策能力吗?但是人肯定有。。。只是你的决策能力的来源于哪里,是现实?还是一些假大空?
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)