記一次httpclient Connection reset問題定位


 

問題:某業務系統在運行一段時間后,某個API一定概率偶現Connection reset現象。

問題定位:

首先想到的是要本地復現出這個問題,但一直復現不出來。

1、根據線上問題相關日志判斷應該是有部分丟包情況。可能是系統參數的設置問題,如果在  net.ipv4.tcp_tw_recycle 、net.ipv4.tcp_timestamps 均設置為1的情況下,可能會因為timestamps時間戳校驗導致部分丟包。
2、查詢了線上配置,lvs、引擎集群的系統參數配置,均是net.ipv4.tcp_tw_recycle=0,net.ipv4.tcp_timestamps=1,不具備出現1描述問題的條件。
3、排查lvs、引擎服務器上和丟包有關日志。如網卡netdev backlog隊列是否溢出,網卡Ring Buffer設置值,半連接隊列溢出值等,tcp的log等,均無異常情況。
4、在開發測試環境模擬多個客戶端(5)個同時壓測,jmeter長/短連接、Timeout時間、HttpClient版本,也未復現該問題,將客戶端的配置改成net.ipv4.tcp_tw_recycle=1,net.ipv4.tcp_timestamps=1,來壓測,排查下是否是客戶端系統參數引起的,看下是否能重現,也未重現該問題。
5、通過httpclient編寫api定時訪問接口,短鏈接下未復現。
6、通過httpclient編寫api訪問接口,使用httpclient連接池,長連接下復現,每次任務sleep 隨機0-60s。(考慮服務端keepalive_timeout時間是60s)。發現出現同樣問題。判斷是長連接情況下導致。
7、研究了下http連接池的長連接原理,默認策略如下。設置的客戶端默認超時時間為-1,即永遠不失效,重寫該方法,設置時間為20s。發現不會出現該問題。

8、但考慮服務端有設置60s的超時時間,不會出現那么大概率的問題

9、可以通過在返回header頭中加入timeout時間,強制給客戶端設置一個長連接超時時間。如

10、去掉默認策略。(因為特殊原因不能讓客戶端改)仍然不能解決問題。

11、修改測試任務發送的時間,發現sleep時間在30S內不會出現該問題,sleep時間在30-60s會50%概率出現。

12、查詢所有鏈路上的(客戶端、lvs、nginx)的相關系統參數超時配置,修改均無效。

13、在設置為32S sleep的場景抓包分析。客戶端抓包如下,發現在32S用同一個連接去發送數據后,服務端返回了一個RST(重置連接)信號。但對比服務端nginx日志,並未發現收到該包。懷疑問題出現在LVS

 14、LVS上抓包,發現是LVS上回復了RST重置連接的包。檢查LVS配置

 

 

15、發現有個如下設置:

ipvsadm --set 30 6 60

 

看說明,應該不會影響功能。在抓包的結果中也發現,客戶端會重新換個連接,重新發一次請求。

 

16、思考良久,在測試代碼中加入了catch,發現catch后就不會進行重新選取連接重試。導致BUG。

17、查看LVS官方文檔,發現三個參數和baidu搜出來的結果不一致。該參數會使TCP連接超時。

18、修改參數為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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM