TIME_WAIT和CLOSE_WAIT狀態區別

在服務器的平常維護過程當中,會常常用到下面的命令:linux

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' 

它會顯示例以下面的信息:服務器

TIME_WAIT 814
CLOSE_WAIT 1
FIN_WAIT1 1
ESTABLISHED 634
SYN_RECV 2
LAST_ACK 1網絡

經常使用的三個狀態是:ESTABLISHED 表示正在通訊,TIME_WAIT 表示主動關閉,CLOSE_WAIT 表示被動關閉。socket

  • TCP協議規定,對於已經創建的鏈接,網絡雙方要進行四次握手才能成功斷開鏈接,若是缺乏了其中某個步驟,將會使鏈接處於假死狀態,鏈接自己佔用的資源不會被釋放。網絡服務器程序要同時管理大量鏈接,因此頗有必要保證無用鏈接徹底斷開,不然大量僵死的鏈接會浪費許多服務器資源。在衆多TCP狀態中,最值得注意的狀態有兩個:CLOSE_WAIT和TIME_WAIT。

TIME_WAITtcp

  • TIME_WAIT 是主動關閉連接時造成的,等待2MSL時間,約4分鐘。主要是防止最後一個ACK丟失。 因爲TIME_WAIT 的時間會很是長,所以server端應儘可能減小主動關閉鏈接

CLOSE_WAITspa

  • CLOSE_WAIT是被動關閉鏈接是造成的。根據TCP狀態機,服務器端收到客戶端發送的FIN,則按照TCP實現發送ACK,所以進入CLOSE_WAIT狀態。但若是服務器端不執行close(),就不能由CLOSE_WAIT遷移到LAST_ACK,則系統中會存在不少CLOSE_WAIT狀態的鏈接。此時,多是系統忙於處理讀、寫操做,而未將已收到FIN的鏈接,進行close。此時,recv/read已收到FIN的鏈接socket,會返回0。

爲何須要 TIME_WAIT 狀態?code

  • 假設最終的ACK丟失,server將重發FIN,client必須維護TCP狀態信息以即可以重發最終的ACK,不然會發送RST,結果server認爲發生錯誤。TCP實現必須可靠地終止鏈接的兩個方向(全雙工關閉),client必須進入 TIME_WAIT 狀態,由於client可能面 臨重發最終ACK的情形。

爲何 TIME_WAIT 狀態須要保持 2MSL 這麼長的時間?server

  • 若是 TIME_WAIT 狀態保持時間不足夠長(好比小於2MSL),第一個鏈接就正常終止了。第二個擁有相同相關五元組的鏈接出現,而第一個鏈接的重複報文到達,干擾了第二個鏈接。TCP實現必須防止某個鏈接的重複報文在鏈接終止後出現,因此讓TIME_WAIT狀態保持時間足夠長(2MSL),鏈接相應方向上的TCP報文要麼徹底響應完畢,要麼被 丟棄。創建第二個鏈接的時候,不會混淆。

TIME_WAIT 和CLOSE_WAIT狀態socket過多

若是服務器出了異常,百分之八九十都是下面兩種狀況:資源

  • 1.服務器保持了大量TIME_WAIT狀態class

  • 2.服務器保持了大量CLOSE_WAIT狀態,簡單來講CLOSE_WAIT數目過大是因爲被動關閉鏈接處理不當致使的。

  • 由於linux分配給一個用戶的文件句柄是有限的,而TIME_WAIT和CLOSE_WAIT兩種狀態若是一直被保持,那麼意味着對應數目的通道就一直被佔着,並且是「佔着茅坑不使勁」,一旦達到句柄數上限,新的請求就沒法被處理了,接着就是大量Too Many Open Files異常,Tomcat崩潰。

做者:InnocenceYWQ 連接:https://www.jianshu.com/p/f6a563f3526c 來源:簡書 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
相關文章
相關標籤/搜索