網路編程:優雅關閉socket/TIME_WAIT/CLOSE_WAIT/SoLinger

來源:互聯網
上載者:User

一個很特別的參數,影響關閉socket後的行為,是立即釋放,還是進入TIME_WAIT狀態並等 待一段時間(單位:秒)才釋放。這個參數,在Socket中可以設定,在Mina2的IoService中也有setSoLinger設定。對於新bs3 架構的Service4Mina2s組件,可以通過以下兩種方法設定。 
<prop key="m_solinger">1</prop><!-- ={-1 | 0 | nSec}--> 
<property name="soLinger"><value>1</value></property><!--僅僅針對伺服器 ={-1 | 0 | nSec}--> 
取值:-1表示使用OS預設參數,0表示立即釋放,nSec表示等待n秒後釋放。 

優雅關閉的幾個步驟:1)shutdown(SEND);2)recv(EOF, 5s);3) closeSocket();4) TIME_WAIT 

參考:http://hi.baidu.com/xingfengsoft/blog/item/021b03ce872e0430b700c89d.html 
【轉自文靜】減少Linux伺服器過多的TIME_WAIT (2009/08/24 22:45) 
TIME_WAIT狀態的意義: 
用戶端與伺服器端建立TCP/IP串連後關閉SOCKET後,伺服器端串連的連接埠狀態為TIME_WAIT 
是不是所有執行主動關閉的socket都會進入TIME_WAIT狀態呢? 
有沒有什麼情況使主動關閉的socket直接進入CLOSED狀態呢? 
主動關閉的一方在發送最後一個 ack 後,就會進入 TIME_WAIT 狀態 停留2MSL(max segment lifetime)時間,這個是TCP/IP必不可少的,也就是“解決”不了的。 
也就是TCP/IP設計者本來是這麼設計的 
主要有兩個原因 
1。防止上一次串連中的包,迷路後重新出現,影響新串連(經過2MSL,上一次串連中所有的重複包都會消失) 
2。可靠的關閉TCP串連。在主動關閉方發送的最後一個 ack(fin) ,有可能丟失,這時被動方會重新發 
fin, 如果這時主動方處於 CLOSED 狀態 ,就會響應 rst 而不是 ack。所以主動方要處於 TIME_WAIT 狀態,而不能是 CLOSED 。 
TIME_WAIT 並不會佔用很大資源的,除非受到攻擊。 
在Squid伺服器中可輸入如下命令: 
#netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' 
LAST_ACK 14 
SYN_RECV 348 
ESTABLISHED 70 
FIN_WAIT1 229 
FIN_WAIT2 30 
CLOSING 33 
TIME_WAIT 18122 
狀態:描述 
CLOSED:無串連是活動的或進行中 
LISTEN:伺服器在等待進入呼叫 
SYN_RECV:一個串連請求已經到達,等待確認 
SYN_SENT:應用已經開始,開啟一個串連 
ESTABLISHED:正常資料轉送狀態 
FIN_WAIT1:應用說它已經完成 
FIN_WAIT2:另一邊已同意釋放 
ITMED_WAIT:等待所有分組死掉 
CLOSING:兩邊同時嘗試關閉 
TIME_WAIT:另一邊已初始化一個釋放 
LAST_ACK:等待所有分組死掉 
也就是說,這條命令可以把當前系統的網路連接狀態分類匯總。 
下面解釋一下為啥要這樣寫: 
一個簡單的管道符串連了netstat和awk命令。 
—————————————————————— 
先來看看netstat: 
netstat -n 
Active Internet connections (w/o servers) 
Proto Recv-Q Send-Q Local Address Foreign Address State 
tcp 0 0 123.123.123.123:80 234.234.234.234:12345 TIME_WAIT 
你實際執行這條命令的時候,可能會得到成千上萬條類似上面的記錄,不過我們就拿其中的一條就足夠了。 
—————————————————————— 
再來看看awk: 
/^tcp/ 
濾出tcp開頭的記錄,屏蔽udp, socket等無關記錄。 
state[] 
相當於定義了一個名叫state的數組 
NF 
表示記錄的欄位數,如上所示的記錄,NF等於6 
$NF 
表示某個欄位的值,如上所示的記錄,$NF也就是$6,表示第6個欄位的值,也就是TIME_WAIT 
state[$NF] 
表示數組元素的值,如上所示的記錄,就是state[TIME_WAIT]狀態的串連數 
++state[$NF] 
表示把某個數加一,如上所示的記錄,就是把state[TIME_WAIT]狀態的串連數加一 
END 
表示在最後階段要執行的命令 
for(key in state) 
遍曆數組 
print key,”/t”,state[key] 
列印數組的鍵和值,中間用/t定位字元分割,美化一下。 
如發現系統存在大量TIME_WAIT狀態的串連,通過調整核心參數解決, 
vim /etc/sysctl.conf 
編輯檔案,加入以下內容: 
net.ipv4.tcp_syncookies = 1 
net.ipv4.tcp_tw_reuse = 1 
net.ipv4.tcp_tw_recycle = 1 
net.ipv4.tcp_fin_timeout = 30 
然後執行 /sbin/sysctl -p 讓參數生效。 
Linux下高並發的Squid伺服器,TCP TIME_WAIT通訊端數量經常達到兩、三萬,伺服器很容易被拖死。通過修改Linux核心參數,可以減少Squid伺服器的TIME_WAIT通訊端數量。 
vi /etc/sysctl.conf 
增加以下幾行:引用 
net.ipv4.tcp_fin_timeout = 30 
net.ipv4.tcp_keepalive_time = 1200 
net.ipv4.tcp_syncookies = 1 
net.ipv4.tcp_tw_reuse = 1 
net.ipv4.tcp_tw_recycle = 1 
net.ipv4.ip_local_port_range = 1024 65000 
net.ipv4.tcp_max_syn_backlog = 8192 
net.ipv4.tcp_max_tw_buckets = 5000 
說明: 
net.ipv4.tcp_syncookies = 1 表示開啟SYN Cookies。當出現SYN等待隊列溢出時,啟用cookies來處理,可防範少量SYN攻擊,預設為0,表示關閉; 
net.ipv4.tcp_tw_reuse = 1 表示開啟重用。允許將TIME-WAIT sockets重新用於新的TCP串連,預設為0,表示關閉; 
net.ipv4.tcp_tw_recycle = 1 表示開啟TCP串連中TIME-WAIT sockets的快速回收,預設為0,表示關閉。 
net.ipv4.tcp_fin_timeout = 30 表示如果通訊端由本端要求關閉,這個參數決定了它保持在FIN-WAIT-2狀態的時間。 
net.ipv4.tcp_keepalive_time = 1200 表示當keepalive起用的時候,TCP發送keepalive訊息的頻度。預設是2小時,改為20分鐘。 
net.ipv4.ip_local_port_range = 1024 65000 表示用於向外串連的連接埠範圍。預設情況下很小:32768到61000,改為1024到65000。 
net.ipv4.tcp_max_syn_backlog = 8192 表示SYN隊列的長度,預設為1024,加大隊列長度為8192,可以容納更多等待串連的網路連接數。 
net.ipv4.tcp_max_tw_buckets = 5000表示系統同時保持TIME_WAIT通訊端的最大數量,如果超過這個數字,TIME_WAIT通訊端將立刻被清除並列印警告資訊。默 認為180000,改為5000。對於Apache、Nginx等伺服器,上幾行的參數可以很好地減少TIME_WAIT通訊端數量,但是對於 Squid,效果卻不大。此項參數可以控制TIME_WAIT通訊端的最大數量,避免Squid伺服器被大量的TIME_WAIT通訊端拖死。 
執行以下命令使配置生效: 
/sbin/sysctl -p 

http://dennis-zane.javaeye.com/blog/206963#comments 2008-06-23 TCP的TIME_WAIT狀態 
主動關閉的Socket端會進入TIME_WAIT狀態,並且持續2MSL時間長度,MSL就是maximum segment lifetime(最大分節生命期),這是一個IP資料包能在互連網上生存的最長時間,超過這個時間將在網路中消失。MSL在RFC 1122上建議是2分鐘,而源自berkeley的TCP實現傳統上使用30秒,因而,TIME_WAIT狀態一般維持在1-4分鐘。 
TIME_WAIT狀態存在的理由: 
1)可靠地實現TCP全雙工系統串連的終止 
在進行關閉串連四路握手協議時,最後的ACK是由主動關閉端發出的,如果這個最終的ACK丟失,伺服器將重發最終的FIN,因此用戶端必須 維護狀態資訊允 許它重發最終的ACK。如果不維持這個狀態資訊,那麼用戶端將響應RST分節,伺服器將此分節解釋成一個錯誤(在java中會拋出connection reset的SocketException)。因而,要實現TCP全雙工系統串連的正常終止,必須處理終止序列四個分節中任何一個分節的丟失情況,主動關閉 的用戶端必須維持狀態資訊進入TIME_WAIT狀態。 
2)允許老的重複分節在網路中消逝 
TCP分節可能由於路由器異常而“迷途”,在迷途期間,TCP發送端可能因確認逾時而重發這個分節,迷途的分節在路由器修複後也會被送到最終目的地,這個 原來的迷途分節就稱為lost duplicate。在關閉一個TCP串連後,馬上又重建立立起一個相同的IP地址和連接埠之間的TCP串連,後一個串連被稱為前一個串連的化身 (incarnation),那麼有可能出現這種情況,前一個串連的迷途重複分組在前一個串連終止後出現,從而被無解成從屬於新的化身。為了避免這個情 況,TCP不允許處於TIME_WAIT狀態的串連啟動一個新的化身,因為TIME_WAIT狀態持續2MSL,就可以保證當成功建立一個TCP串連的時 候,來自串連先前化身的重複分組已經在網路中消逝。 
新的SCTP協議通過在訊息頭部添加驗證標誌避免了TIME_WAIT狀態。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.