解決TIME_WAIT過多造成的問題


 

sh-4.1# netstat -an |awk '/tcp/ {++S[$NF]}END {for (a in S) print a , S[a]}'
TIME_WAIT 41
CLOSE_WAIT 1
ESTABLISHED 2
LISTEN 7

TCP/IP TIME_WAIT狀態原理:

通信雙方建立TCP連接后,主動關閉連接的一方就會進入TIME_WAIT狀態
客戶端主動關閉連接時,會發送最后一個ack后,然后會進入TIME_WAIT狀態,再停留2個MSL時間(后有MSL的解釋),進入CLOSED狀態。
下圖是以客戶端主動關閉連接為例,說明這一過程的:
為什么TIME_WAIT狀態還需要等2MSL后才能返回到CLOSED狀態?

這是因為:雖然雙方都同意關閉連接了,而且握手的4個報文也都協調和發送完畢,按理可以直接回到CLOSED狀態(就好比從SYN_SEND狀態到 ESTABLISH狀態那樣);但是因為我們必須要假想網絡是不可靠的,你無法保證你最后發送的ACK報文會一定被對方收到,因此對方處於 LAST_ACK狀態下的SOCKET可能會因為超時未收到ACK報文,而重發FIN報文,所以這個TIME_WAIT狀態的作用就是用來重發可能丟失的 ACK報文,並保證於此。

CLOSED:無連接是活動的或正在進行
LISTEN:服務器在等待進入呼叫
SYN_RECV:一個連接請求已經到達,等待確認
SYN_SENT:應用已經開始,打開一個連接
ESTABLISHED:正常數據傳輸狀態
FIN_WAIT1:應用說它已經完成
FIN_WAIT2:另一邊已同意釋放
ITMED_WAIT:等待所有分組死掉
CLOSING:兩邊同時嘗試關閉
TIME_WAIT:另一邊已初始化一個釋放
LAST_ACK:等待所有分組死掉

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

服務器出現導常都是下需的兩種狀態:

1.服務器保持了大量TIME_WAIT狀態
2.服務器保持了大量CLOSE_WAIT狀態

因為linux分配給一個用戶的文件句柄是有限的,而TIME_WAIT和CLOSE_WAIT兩種狀態如果一直被保持,那么意味着對應數目的通道就一直被占着,並只是占不用,一旦達到句柄數上限,新的請求就無法被處理了,接着就是大量Too Many Open Files異常,tomcat崩潰!

優化系統內核參 數解決TIME_WAIT可能很容易,但是應對CLOSE_WAIT的情況還是需要從程序本身出發。現在來分別說說這兩種情況的處理方法:

爬蟲服務器或者WEB服務器如果沒有做內核參數優化,就會出現大量的TIME_WAIT狀態。TIME_WAIT是主動關閉連接的一方保持的狀態,對於爬蟲服務器來說他本身就是“客戶端”,在完成一個爬取任務之后,他就 會發起主動關閉連接,從而進入TIME_WAIT的狀態,然后在保持這個狀態2MSL(max segment lifetime)時間之后,徹底關閉回收資源。

 

sh-4.1# cat /etc/sysctl.conf|awk '/net.ipv4.tcp_syncookies|net.ipv4.tcp_tw_reuse|net.ipv4.tcp_tw_recycle|net.ipv4.tcp_fin_timeout/'
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30

 

使參數生效:

sh-4.1# sysctl -p

 

 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 修改系默認的 TIMEOUT 時間
其它參數說明:
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套接字拖死。

注:
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
設置這兩個參數: reuse是表示是否允許重新應用處於TIME-WAIT狀態的socket用於新的TCP連接; recyse是加速TIME-WAIT sockets回收
相關參數

 


免責聲明!

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



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