前言
前段時間遇到一個問題,由於是初次相識,所以寫一篇小筆記記錄一下。以免後面再次遇到類似的問題,可以參考提供解決問題的思路。當時是由於一個同事在群裡發了一張截圖,原來是一個服務掛掉了。當時看到他發的異常資訊日誌,完全是一臉懵逼,這問題從來沒遇到過啊。。。這下難搞了。 問題概述
當時同事發過來的頁面異常資訊是這樣的
當時看到這個頁面完全沒有思緒,沒有辦法只好串連遠程伺服器,看到tomcat上也報異常了,沒辦法只好嘗試著去重啟tomcat,可是tomcat好像也啟動不了。而且報另外一個異常,而我也被這個異常資訊帶偏了。tomcat上的異常資訊是這樣的
上面的異常資訊是顯示資料庫連接池建立失敗。這裡想到難道是項目的資料庫連接出現問題。檢查了資料庫是正常的,可以使用,難道是資料來源配置出現問題。可是之前部署到tomcat上還是可以的。不應該是資料來源配置出現問題,後來想是不是因為換了tomcat部署,而tomcat上可能配置了資料來源,可是檢查了一下,探索資料源也是正常的,沒任何毛病。沒辦法只好請教了同事,可是同事也沒有提出什麼好的建議,這下徹底傻眼了。
慶幸的是,我們還有一位最好的老師,那就是度娘。可是網上也說可能是資料來源配置問題。可是檢查了就是沒毛病,這就為難了。當時部門的小夥伴都回去。組長和經理開完會回來,我把我的問題向組長描述了一下,組長說重啟一下伺服器就ok了。由於當時不早了,所以組長說完就打算回去了,我也就沒多問。打算第二天來重啟一下試一試。 沒什麼是重啟不能解決的
第二天上班過來,我遠程重啟了伺服器,然後重啟了tomcat重新發布了項目,結果居然好了。但是具體是什麼原因導致這種情況出現。心中很是疑惑。。。又在網上了尋找了一些資料,可是沒找到原因。後來我又看了一次同事發給我的異常資訊圖片,既然tomcat啟動報錯的原因找不到,說不定可以從最初的異常發生來找原因。我找了一下,網上有提到相關原因,聯想到自己的項目,完全吻合。
由於這個項目中,有很多服務介面。而在另外一個項目中有一個功能用httpclient同時調用這些介面,通過httpclient調用時需要建立串連,由於並發或者請求過多導致,由於大量串連處於time-wait,這樣就導致了很多伺服器的資源被大量消耗。說到這個time-wait狀態,這裡就要重新複習一下TCP的四次揮手,借用一下《掃盲系列之Http長串連短串連》的圖
在tcp中斷連線的過程中,需要四次揮手,這裡的揮手是相對建立串連的三向交握而言。在服務端發送中斷連線請求之後(這裡需要注意用戶端也是可以主動發起中斷連線的請求),用戶端接收到服務端的中斷連線請求,他會回應服務端,他已經收到斷開請求,但是用戶端不會馬上中斷連線,因為用戶端可能還有資料包沒有發送完畢。所以用戶端不會馬上中斷連線,而是等自己這邊的資料發送完畢再中斷連線,然後再發送一個finish響應。服務端收到用戶端的finish響應會再次發送一個ACK來確認用戶端是否已經中斷連線,由於網路的延遲等其他原因,服務端需要等待一段時間,這段時間就是上圖的2MSL,而這段時間的串連都是出於time-wait狀態。在一段時間之後串連才徹底斷開變為closed狀態。而如果請求很多,導致很多串連出於time-wait狀態就會導致No buffer space available的產生。後來我在本地簡單類比多次請求,然後通過是netstat -n來查看串連情況,確實看到很多串連出於time-wait狀態,截圖如下
重啟只能救場,不能根治
上面的問題,雖然重啟伺服器能夠立馬釋放socket串連(注意這裡不是重啟tomcat伺服器),但是這種方式只是治標不治本,這種問題後面可能還會出現,對於這種問題,應該從代碼和硬體角度來考慮解決。首先代碼中對於httpclient建立的串連應該及時關閉,同時還可以修改伺服器的註冊表,提高socket可用串連數,同時減少time-wait時間,讓處於time-wait狀態的串連儘快釋放。 總結
上面是對於自己遇到的問題的一份小總結,對於這個問題的解決辦法,如果有更好的解決思路,還請留言指教。