记一次httpclient Connection reset问题定位

 

问题:某业务系统在运行一段时间后,某个API必定几率偶现Connection reset现象。html

问题定位:nginx

首先想到的是要本地复现出这个问题,但一直复现不出来。api

一、根据线上问题相关日志判断应该是有部分丢包状况。多是系统参数的设置问题,若是在  net.ipv4.tcp_tw_recycle 、net.ipv4.tcp_timestamps 均设置为1的状况下,可能会由于timestamps时间戳校验致使部分丢包。
二、查询了线上配置,lvs、引擎集群的系统参数配置,均是net.ipv4.tcp_tw_recycle=0,net.ipv4.tcp_timestamps=1,不具有出现1描述问题的条件。
三、排查lvs、引擎服务器上和丢包有关日志。如网卡netdev backlog队列是否溢出,网卡Ring Buffer设置值,半链接队列溢出值等,tcp的log等,均无异常状况。
四、在开发测试环境模拟多个客户端(5)个同时压测,jmeter长/短链接、Timeout时间、HttpClient版本,也未复现该问题,将客户端的配置改为net.ipv4.tcp_tw_recycle=1,net.ipv4.tcp_timestamps=1,来压测,排查下是不是客户端系统参数引发的,看下是否能重现,也未重现该问题。
五、经过httpclient编写api定时访问接口,短连接下未复现。
六、经过httpclient编写api访问接口,使用httpclient链接池,长链接下复现,每次任务sleep 随机0-60s。(考虑服务端keepalive_timeout时间是60s)。发现出现一样问题。判断是长链接状况下致使。
七、研究了下http链接池的长链接原理,默认策略以下。设置的客户端默认超时时间为-1,即永远不失效,重写该方法,设置时间为20s。发现不会出现该问题。

八、但考虑服务端有设置60s的超时时间,不会出现那么大几率的问题服务器

九、能够经过在返回header头中加入timeout时间,强制给客户端设置一个长链接超时时间。如tcp

十、去掉默认策略。(由于特殊缘由不能让客户端改)仍然不能解决问题。测试

十一、修改测试任务发送的时间,发现sleep时间在30S内不会出现该问题,sleep时间在30-60s会50%几率出现。.net

十二、查询全部链路上的(客户端、lvs、nginx)的相关系统参数超时配置,修改均无效。3d

1三、在设置为32S sleep的场景抓包分析。客户端抓包以下,发如今32S用同一个链接去发送数据后,服务端返回了一个RST(重置链接)信号。但对比服务端nginx日志,并未发现收到该包。怀疑问题出如今LVS日志

 1四、LVS上抓包,发现是LVS上回复了RST重置链接的包。检查LVS配置htm

 

 

1五、发现有个以下设置:

ipvsadm --set 30 6 60

 

看说明,应该不会影响功能。在抓包的结果中也发现,客户端会从新换个链接,从新发一次请求。

 

1六、思考良久,在测试代码中加入了catch,发现catch后就不会进行从新选取链接重试。致使BUG。

1七、查看LVS官方文档,发现三个参数和baidu搜出来的结果不一致。该参数会使TCP链接超时。

1八、修改参数为set 60 6 60,(加上参数的目的是为了缓解长链接 的四层tcp耗尽攻击)。问题解决。

至此,问题定位完成。要保证lvs的tcp established超时时间大于nginx的keepalive超时时间。

参考:http://www.austintek.com/LVS/LVS-HOWTO/HOWTO/LVS-HOWTO.ipvsadm.html

https://dongliboyqq.iteye.com/blog/2409122

https://blog.csdn.net/qq_35440040/article/details/83543954

相关文章
相关标签/搜索