TIME_WAIT
表示客戶端主動關閉socket。
原因:
- 大量的短連接存在
- 特別是 HTTP 請求中,如果 connection 頭部取值被設置為 close 時,基本都由服務端發起主動關閉連接
- TCP 四次揮手關閉連接機制中,為了保證 ACK 重發和丟棄延遲數據,設置 time_wait 為 2 倍的 MSL(報文最大存活時間)
后果:
- TCP 連接中,「主動發起關閉連接」的一端,會進入 time_wait 狀態
- time_wait 狀態,默認會持續 2 MSL(報文的最大生存時間),一般是 2x2 mins
- time_wait 狀態下,TCP 連接占用的端口,無法被再次使用;TCP 端口數量,上限是 6.5w(65535,16 bit)
- 大量 time_wait 狀態存在,會導致新建 TCP 連接會出錯,address already in use : connect 異常
- 占用內存,但內存占用並不大,1萬條TIME_WAIT的連接,也就多消耗1M
- 耗CPU,每次找到一個隨機端口,需要遍歷一遍bound ports的吧,這必然需要一些CPU時間,但也還好,無需太擔憂
解決:
- 服務器端允許 time_wait 狀態的 socket 被重用
- 縮減 time_wait 時間,設置為 1 MSL
- 修改內核參數:
- net.ipv4.tcp_tw_recycle = 1
- net.ipv4.tcp_tw_reuse = 1
- net.ipv4.tcp_timestamps = 1
- https://zhuanlan.zhihu.com/p/40013724
CLOSE_WAIT
表示服務端被動關閉socket。
根據TCP狀態機,服務器端收到客戶端發送的FIN,則按照TCP實現發送ACK,因此進入CLOSE_WAIT狀態。但如果服務器端不執行close(),就不能由CLOSE_WAIT遷移到LAST_ACK,則系統中會存在很多CLOSE_WAIT狀態的連接。
原因:應用程序寫的有問題,沒有合適的關閉socket;要么是服務器CPU處理不過來(CPU太忙)或者應用程序一直睡眠到其它地方(鎖,或者文件I/O等等),應用程序獲得不到合適的調度時間,造成程序沒法真正的執行close操作。
后果:出現大量的CLOSE_WAIT后,服務無法繼續正常服務,端口無法被復用,socket資源被耗盡。因為Linux分配給一個用戶的文件句柄是有限的,而如果一直被保持,則文件句柄也就不能close,導致句柄資源達到上線,接着就會出現大量Too Many Open Files錯誤。