No buffer space available (maximum connections reached?)問題的最終解決

前段時間在項目維護當中遇見一個問題,方便以後再次遇見類似的問題,可以參考解決問題的思路,記錄如下:

問題概述:

維護項目當中,客戶這邊發來消息,稱自己的網站登錄不上去了,提示用戶名密碼錯誤,我就登錄到服務器上查看系統日誌和報錯情況,如圖:

這個異常來源部署的一個jar包,用於讀取數據存入mongodb,再看了Tomcat也報錯了,錯誤是:java.net.SocketException。看完這樣的問題後,沒有確切的解決方案,自己一臉懵逼無奈的重新啓動服務,可以正常登陸。沒有什麼問題是重啓解決不了的。

問題分析:

雖然重啓服務能暫時以最快的速度解決問題,但是問題很容易復現,很明顯,這個並不是根本的解決方案。

需要進行進一步的分析:

總結下來根據我們當時的代碼和部署的系統有可能出現的原因:

1:因爲首先看到的是mongodb的問題,所以猜測是mongodb鏈接數不夠,而需要等待的鏈接數過多,導致資源無法儘快釋放。

2:因爲代碼內部使用有很多的 HttpClient請求,調用另一個數據庫的數據,可能是請求量過多,或者是請求未正常的關閉。導致內部資源泄露

3:系統併發量太大,鏈接數過多,部分系統或者非系統請求無法正常的釋放關閉,而又持續請求,導致socket鏈接不斷進行積壓,從而導致系統崩潰。

根據以上分析,我們對系統進行了內部的測試。讓錯誤重現。

 

 

 

通過cmd輸入netstat -an 發現有大量處於TIME_WAIT狀態的TCP鏈接,也就是那些Socket未釋放的鏈接 

 

那麼TIME_WAIT狀態的來由是什麼呢?

TCP鏈接需要三次握手,四次揮手。可以參考下面流程圖:

三次握手建立連接示意圖

 四次握手關閉連接示意圖

從上面的三次握手建立連接示意圖中可以知道,只要client端和server端都接收到了對方發送的ACK應答之後,雙方就可以建立連接,之後就可以進行數據交互了,這個過程需要三步。

而四次握手關閉連接示意圖中,TCP協議中,關閉TCP連接的是Server端(當然,關閉都可以由任意一方發起),當Server端發起關閉連接請求時,向Client端發送一個FIN報文,Client端收到FIN報文時,很可能還有數據需要發送,所以並不會立即關閉SOCKET,所以先回復一個ACK報文,告訴Server端,“你發的FIN報文我收到了”。當Client端的所有報文都發送完畢之後,Client端向Server端發送一個FIN報文,此時Client端進入關閉狀態,不在發送數據。

Server端收到FIN報文後,就知道可以關閉連接了,但是網絡是不可靠的,Client端並不知道Server端要關閉,所以Server端發送ACK後進入TIME_WAIT狀態,如果Client端沒有收到ACK則Server段可以重新發送。Client端收到ACK後,就知道可以斷開連接了。Server端等待了2MSL(Max Segment Lifetime,最大報文生存時間)後依然沒有收到回覆,則證明Client端已正常斷開,此時,Server端也可以斷開連接了。2MSL的TIME_WAIT等待時間就是由此而來。

我們知道了TIME_WAIT的由來,TIME_WAIT 狀態最大保持時間是2 * MSL,在1-4分鐘之間,所以當系統併發過大,Client-Server連接數過多,Server端會在1-4分鐘之內積累大量處於TIME_WAIT狀態的無法釋放的socket連接,導致服務器效率急劇下降,甚至耗完服務器的所有資源,最終導致No buffer space available (maximum connections reached?): connect
問題的發生

最終解決辦法:

1:關閉不需要的鏈接:

檢查在代碼當中是否有請求完的鏈接沒有正常關閉,如:HttpClient請求中鏈接是否正常關閉, 
Mongodb讀取數據時鏈接是否正常關閉,及時關閉請求鏈接和clean,使用
 

    try{}catch(){}finally{}

    釋放請求,及時回收資源,避免內存溢出。

2:通過修改註冊表進行配置,減少等待時間


通過regedit啓動註冊表編譯器找到如下路徑:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

 

添加參數:

(1)新建

值名稱:MaxUserPort

值類型:DWORD

值數據:65534(十六進制是FFFE

有效範圍:5000 - 65534 (十進制)

默認:0x1388 5000(十進制)

(2)新建

值名稱:TCPTimedWaitDelay

值類型:DWORD

值數據:0000001e(30) 

 

發佈了122 篇原創文章 · 獲贊 28 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章