記一次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

相關文章
相關標籤/搜索