tcp連接出現close_wait狀態?可能是代碼不夠健壯


姊妹篇:

服務器出現大量close_wait,我們來說說到底是怎么回事?(以tomcat為例)

  

一、問題概述

今天遇到個小問題。

我們的程序依賴了大數據那邊的服務,大數據那邊提供了restful接口供我們調用。

測試反映接口有問題,我在本地重現了。

我這邊感覺抓包可能對分析問題有用,就用wireshark抓包了。然后發給大數據的同事看了下,是他們的問題。

然后就幫忙把問題解決了。

然后我這邊重新測試,自己抓包了下,結果反而發現我方程序的一個問題。

 

下圖,是我方和大數據方的交互數據包。

 

前三個為tcp連接建立,中間(序號4,5,6)為http請求響應,序號7-8為大數據方在請求完畢后關閉連接。

好了,看下面的圖:(下面這個tcp狀態變遷圖網上到處都是,一定要學會看。)

 

我們重點關注下面紅色部分:

當一個tcp實體(以我方為例),當我方和大數據方建立連接后,一直處於下面的established狀態。

上圖紅色框框起來的部分表示:

收到對方的FIN(上圖紅色的recv:FIN),我方回應ACK。(上圖紅色的send:ACK)。

然后我方進入了CLOSE_WAIT狀態。

 

於是我就去cmd里面查看下:

 

 果然存在這個close_wait狀態的連接。

但是過了沒特別久,一兩分鍾吧,這個狀態自己消失了。(猜測是操作系統設置了close_wait超時時間,超時后主動發起fin請求斷開連接)

暫時還沒找到原因,大佬知道的話,還請告知下(我的是win7 64位)。

 

二、關於close_wait

這個狀態要怎么才能進入下一個狀態(LAST_ACK)呢?

看最上面的變遷圖可以知道,我方tcp實體只要發起一個FIN即可。這個FIN怎么才能發起呢?

那就需要程序主動去關閉連接。

我看了下代碼,果然是我方的httpclient使用完了沒關閉。。(右邊是我改后的代碼,,下面把被關閉的兩個變量的完整類名也展示一下)

org.apache.http.impl.client.CloseableHttpClient.CloseableHttpClient httpClient;
org.apache.http.client.methods.CloseableHttpResponse.CloseableHttpResponse response;

 

 

 再看我上面的抓包的圖的最后兩行:

 

過了一定時間后,我方可能是在close_wait狀態下持續了一定時間,觸發了超時,主動向對方發起了FIN。

但是呢,對方其實已經關閉連接了,所以就返回了RST。(對方已經把連接刪除了)

 

我把程序照上面修改后,重新請求了一次:(已經恢復正常了,如下)

 

三、close_wait過多怎么辦

結論先說:改代碼。

 我方程序上線的話,部署在服務器上,close_wait過多,會導致新建立到大數據方的tcp連接失敗(因為端口未釋放的原因。)

這個問題,就是本端tcp實體(被動關閉的一端)沒有主動關閉連接,大部分都是程序的問題。

要改的話,還是具體看看哪個程序有問題,找到具體的程序后(通過查看有大量close_wait狀態的程序的pid),

再看程序里和哪個遠端host的連接處於該狀態。

然后再去程序里找對應的代碼,修改即可。

 

部分網上的文章,是運維手動清楚close_wait。或者修改close_wait的超時時間。

這個可以解決問題,但是為了程序的健壯性着想,建議還是修改程序吧。

在服務器與客戶端通信過程中,因服務器發生了socket未關導致的closed_wait發生,致使監聽port打開的句柄數到了1024個,且均處於close_wait的狀態,最終造成配置的port被占滿出現“Too many open files”,無法再進行通信。

這個可以參考:

https://blog.csdn.net/wwd0501/article/details/78674170

 

https://blog.csdn.net/mnasd/article/details/80496032

 


免責聲明!

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



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