tcp釋放連接的close_wait, FIN_WAIT2, TIME_WAIT大量存在的原因及解決辦法

存在close_wait的原因和解決辦法

close_wait這個狀態存在於服務端,當服務端發送FIN(之前客戶端已經發送過fin),請求關閉連接之後進入close_wait,然而沒有收到客戶端的響應,可能由於客戶端掉線了(如網絡故障或者掉電),沒有及時給予客戶端回覆造成問題。
或者由於客戶端已經調用close(socket)退出,而服務端對其監測並斷開連接,這種是服務端問題。

解決方法:一般是編程問題,可用keep_alive機制加以解決

存在FIN_WAIT2的原因和解決辦法

這個狀態存在於主動發起斷開請求的一端,如果服務器存在大量的這個狀態,那麼這個服務器就充當客戶端的角色,如網絡爬蟲,出現的原因是由於客戶端發起FIN請求結束連接之後,收到了服務端的應答之後進入FIN_WAIT2,之後就沒收到服務端發送的FIN信號導致。
解決方法:可以配置FIN_WAIT2的時長,當超過時長後自動斷開加以解決(/proc/sys/net/ipv4/tcp_fin_timeout參數)

存在TIME_WAIT的原因和解決辦法

爲什麼要經過TIME_WAIT狀態後才真正關閉連接?
這個有兩個原因:其一是響應服務端發送的FIN報文,保證服務端斷開連接;其二是保證之前請求斷開連接的請求,由於網絡原因滯留在網絡中,後續又到達了,導致後面重新建立的連接斷開。

time_wait大量存在問題的原因:time_wait狀態存在於主動關閉連接的一端(即客戶端),如果是time_wait狀態太多了,那肯定是客戶端程序有問題,一般屬於客戶端頻繁的往服務端發請求,如運行網絡爬蟲的機器上處於time_wait狀態的socket會比較多
解決方法:可以通過修改系統配置和客戶端程序解決
說明:

  1. time_wait相關的內核參數有下面幾個:

    root@ /proc/sys/net/ipv4]$ ls |grep tw
    tcp_max_tw_buckets
    tcp_tw_ignore_syn_tsval_zero
    tcp_tw_recycle
    tcp_tw_recycle_private_only
    tcp_tw_reuse  
    tcp_tw_timeout #系統回收timewait狀態的socket的時長
    

    這些參數的含義可以通過man tcp查看,下面僅貼出部分參數的說明:

    tcp_max_tw_buckets (integer; default: see below; since Linux 2.4)
                  The  maximum  number  of  sockets  in TIME_WAIT state allowed in the system.  This limit exists only to prevent simple denial-of-service attacks.  The default  value of NR_FILE*2 is adjusted depending on the memory in the system.  If this number is exceeded, the socket is closed and a warning is printed.
                  
    tcp_tw_recycle (Boolean; default: disabled; since Linux 2.4)
                  Enable fast recycling of TIME_WAIT sockets.  Enabling this option  is  not  recom-mended  since this causes problems when working with NAT (Network Address Transla-tion).
    
    tcp_tw_reuse (Boolean; default: disabled; since Linux 2.4.19/2.6)
                  Allow to reuse TIME_WAIT sockets for new connections when it is safe from protocol viewpoint. It should not be changed without advice/request of technical experts.
                  
    

    可以調整tcp_tw_timeout,tcp_tw_reuse參數來快速回收tcp TIME_WAIT狀態的socket(不建議調整tcp_tw_recycle選項快速回收)

  2. 調整客戶端程序,採取一些限頻措施(可以使用連接池,緩存等技術,以減少客戶端發起的請求數)

處理這類問題的實用命令

  • netstat
    用netstat命令可以查看系統的socket存在情況

    #netstat -tan|awk '$1~/tcp/{print $NF}'|sort|uniq -c|sort -nr
    156  TIME_WAIT
    141  FIN_WAIT2
    80  ESTABLISHED
    10  LISTEN
    3 CLOSE_WAIT
    2 LAST_ACK
    
  • ss
    通過ss命令我們可以看到timer的內部狀態,以便用於確認處於WAIT狀態socket是否被正常回收掉了。其實這邊用ss也可以替代netstat來排查問題。
    查看man ss:

    SS(8)
    
    NAME
           ss - another utility to investigate sockets
    
    SYNOPSIS
           ss [options] [ FILTER ]
    
    DESCRIPTION
           ss  is  used to dump socket statistics. It allows showing information similar to netstat.  It can
           display more TCP and state informations than other tools.
    

    從man說明中可以知道這是一個可以查看socket信息的工具,和netstat類似,可以顯示更詳細的tcp狀態信息。常用的option有:

    -a: 顯示所有
    -l: 僅顯示listening狀態的
    -p: 
    -t|-u|-w|-x:僅顯示tcp|udp|raw|unix類型的socket信息
    --socket=QUERY:按類型過濾,其中QUERY := {all|inet|tcp|udp|raw|unix|packet|netlink}[,QUERY]
    -D, --diag=FILE : 輸出到文件(Dump raw information about TCP sockets to FILE)
    -o, --options: 用於顯示timer的狀態(show timer information),常和state一起使用,用於查看某個state相關的timer,state有:all,syn-send,syn-recv,established,last-ack,listening,close-wait,time-wait,connected,fin-wait-{1,2},closeing,closed等等
    -s, --summary: 顯示socket使用概況(show socket usage summary)
    

    其中一些示例如下:

    # ss -s
    Total: 647 (kernel 0)
    TCP:   165 (estab 60, closed 83, orphaned 0, synrecv 0, timewait 60/0), ports 0
    
    Transport Total     IP        IPv6
    *         0         -         -        
    RAW       2         1         1        
    UDP       16        16        0        
    TCP       82        82        0        
    INET      100       99        1        
    FRAG      0         0         0        
    
    # ss -o state time-wait 
    Recv-Q Send-Q                        Local Address:Port                            Peer Address:Port   
    0      0                               192.168.1.55:39003                            192.168.1.55:23001    timer:(timewait,45sec,0)
    
    其中, ss state {state_value}
    state_value有如下選項可用:
    syn-sent 發送同步信號
    syn-recv 接收同步信號
    established	建立連接
    fin-wait-{1,2}	等待 完成	2
    time-wait	等待時間	2
    closed	關閉	111
    Close-wait	等待關閉	2
    Last-ack	最後確認
    listening 堅聽	32
    closing	關閉	1
    
    all : 所有以上10種狀態
    connected : 除了 listening and closed 的剩所有狀態(8種狀態)
    synchronized :所有 connected 除了 syn-sent (7種狀態)
    bucket : 顯示狀態爲maintained as minisockets,如:time-wait和syn-recv.(2種狀態)
    big : 和bucket相反.(8種狀態)
    

參考鏈接:
Linux系統使用ss命令查看端口狀態

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