通訊系統經驗談【一】TCP連接狀態分析:SYNC_RECV,CLOSE_WAIT,TIME_WAIT

摘自:http://maoyidao.iteye.com/blog/1744277

面試時看到應聘者簡歷中寫精通網絡,TCP編程,我常問一個問題,TCP建立連接需要幾次握手?95%以上的應聘者都能答對是3次。問TCP斷開連接需要幾次握手,70%的應聘者能答對是4次通訊。再問CLOSE_WAIT,TIME_WAIT是什麼狀態,怎麼產生的,對服務有什麼影響,如何消除?有一部分同學就回答不上來。不是我扣細節,而是在通訊爲主的前端服務器上,必須有能力處理各種TCP狀態。比如統計在本廠的一臺前端機上高峯時間TCP連接的情況,統計命令:

 

 

Linux shell代碼  收藏代碼
  1. netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'  
 

 

結果:

 

除了ESTABLISHED,可以看到連接數比較多的幾個狀態是:FIN_WAIT1, TIME_WAIT, CLOSE_WAIT, SYN_RECV和LAST_ACK;下面的文章就這幾個狀態的產生條件、對系統的影響以及處理方式進行簡單描述。

 

TCP狀態

TCP狀態如下圖所示:

可能有點眼花繚亂?再看看這個時序圖


 

下面看下大家一般比較關心的三種TCP狀態

SYN_RECV 

服務端收到建立連接的SYN沒有收到ACK包的時候處在SYN_RECV狀態。有兩個相關係統配置:

 

1,net.ipv4.tcp_synack_retries :INTEGER

默認值是5

對於遠端的連接請求SYN,內核會發送SYN + ACK數據報,以確認收到上一個 SYN連接請求包。這是所謂的三次握手( threeway handshake)機制的第二個步驟。這裏決定內核在放棄連接之前所送出的 SYN+ACK 數目。不應該大於255,默認值是5,對應於180秒左右時間。通常我們不對這個值進行修改,因爲我們希望TCP連接不要因爲偶爾的丟包而無法建立。

2,net.ipv4.tcp_syncookies

一般服務器都會設置net.ipv4.tcp_syncookies=1來防止SYN Flood攻擊。假設一個用戶向服務器發送了SYN報文後突然死機或掉線,那麼服務器在發出SYN+ACK應答報文後是無法收到客戶端的ACK報文的(第三次握手無法完成),這種情況下服務器端一般會重試(再次發送SYN+ACK給客戶端)並等待一段時間後丟棄這個未完成的連接,這段時間的長度我們稱爲SYN Timeout,一般來說這個時間是分鐘的數量級(大約爲30秒-2分鐘)。

 

這些處在SYNC_RECV的TCP連接稱爲半連接,並存儲在內核的半連接隊列中,在內核收到對端發送的ack包時會查找半連接隊列,並將符合的requst_sock信息存儲到完成三次握手的連接的隊列中,然後刪除此半連接。大量SYNC_RECV的TCP連接會導致半連接隊列溢出,這樣後續的連接建立請求會被內核直接丟棄,這就是SYN Flood攻擊。

 

能夠有效防範SYN Flood攻擊的手段之一,就是SYN Cookie。SYN Cookie原理由D. J. Bernstain和 Eric Schenk發明。SYN Cookie是對TCP服務器端的三次握手協議作一些修改,專門用來防範SYN Flood攻擊的一種手段。它的原理是,在TCP服務器收到TCP SYN包並返回TCP SYN+ACK包時,不分配一個專門的數據區,而是根據這個SYN包計算出一個cookie值。在收到TCP ACK包時,TCP服務器在根據那個cookie值檢查這個TCP ACK包的合法性。如果合法,再分配專門的數據區進行處理未來的TCP連接。

 

觀測服務上SYN_RECV連接個數爲:7314,對於一個高併發連接的通訊服務器,這個數字比較正常。

CLOSE_WAIT

發起TCP連接關閉的一方稱爲client,被動關閉的一方稱爲server。被動關閉的server收到FIN後,但未發出ACK的TCP狀態是CLOSE_WAIT。出現這種狀況一般都是由於server端代碼的問題,如果你的服務器上出現大量CLOSE_WAIT,應該要考慮檢查代碼。

TIME_WAIT

根據TCP協議定義的3次握手斷開連接規定,發起socket主動關閉的一方 socket將進入TIME_WAIT狀態。TIME_WAIT狀態將持續2個MSL(Max Segment Lifetime),在Windows下默認爲4分鐘,即240秒。TIME_WAIT狀態下的socket不能被回收使用. 具體現象是對於一個處理大量短連接的服務器,如果是由服務器主動關閉客戶端的連接,將導致服務器端存在大量的處於TIME_WAIT狀態的socket, 甚至比處於Established狀態下的socket多的多,嚴重影響服務器的處理能力,甚至耗盡可用的socket,停止服務。

 

爲什麼需要TIME_WAIT?TIME_WAIT是TCP協議用以保證被重新分配的socket不會受到之前殘留的延遲重發報文影響的機制,是必要的邏輯保證。

 

和TIME_WAIT狀態有關的系統參數有一般由3個,本廠設置如下:

net.ipv4.tcp_tw_recycle = 1

net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_fin_timeout = 30

 

net.ipv4.tcp_fin_timeout,默認60s,減小fin_timeout,減少TIME_WAIT連接數量。

 

net.ipv4.tcp_tw_reuse = 1表示開啓重用。允許將TIME-WAIT sockets重新用於新的TCP連接,默認爲0,表示關閉;

net.ipv4.tcp_tw_recycle = 1表示開啓TCP連接中TIME-WAIT sockets的快速回收,默認爲0,表示關閉。

 

下一篇:http://maoyidao.iteye.com/blog/1744309 “通訊系統經驗談【二】解讀內核參數 - socket/文件句柄資源限制參數”會向大家介紹本廠網絡相關設置中的其他選項,特別是系統資源限制相關的內核配置。

 

  • 大小: 22.7 KB
  • 大小: 108.9 KB
  • 大小: 217 KB

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章