您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“TIME_WAIT過多造成的問題如何解決”,內容詳細,步驟清晰,細節處理妥當,希望這篇“TIME_WAIT過多造成的問題如何解決”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
1、time_wait的作用:
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連接的時候,來自連接先前化身的重復分組已經在網絡中消逝。
2、大量TIME_WAIT造成的影響:
在高并發短連接的TCP服務器上,當服務器處理完請求后立刻主動正常關閉連接。這個場景下會出現大量socket處于TIME_WAIT狀態。如果客戶端的并發量持續很高,此時部分客戶端就會顯示連接不上。
我來解釋下這個場景。主動正常關閉TCP連接,都會出現TIMEWAIT。
為什么我們要關注這個高并發短連接呢?有兩個方面需要注意:
1)高并發可以讓服務器在短時間范圍內同時占用大量端口,而端口有個0~65535的范圍,并不是很多,刨除系統和其他服務要用的,剩下的就更少了。
2)在這個場景中,短連接表示“業務處理+傳輸數據的時間 遠遠小于 TIMEWAIT超時的時間”的連接。
這里有個相對長短的概念,比如取一個web頁面,1秒鐘的http短連接處理完業務,在關閉連接之后,這個業務用過的端口會停留在TIMEWAIT狀態幾分鐘,而這幾分鐘,其他HTTP請求來臨的時候是無法占用此端口的(占著茅坑不拉翔)。單用這個業務計算服務器的利用率會發現,服務器干正經事的時間和端口(資源)被掛著無法被使用的時間的比例是 1:幾百,服務器資源嚴重浪費。(說個題外話,從這個意義出發來考慮服務器性能調優的話,長連接業務的服務就不需要考慮TIMEWAIT狀態。同時,假如你對服務器業務場景非常熟悉,你會發現,在實際業務場景中,一般長連接對應的業務的并發量并不會很高。
綜合這兩個方面,持續的到達一定量的高并發短連接,會使服務器因端口資源不足而拒絕為一部分客戶服務。同時,這些端口都是服務器臨時分配,無法用SO_REUSEADDR選項解決這個問題。
3、案列分析:
首先,根據一個查詢TCP連接數,來說明這個問題。
netstat -ant|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: 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]狀態的連接數加1 END 表示在最后階段要執行的命令 for(key in state) 遍歷數組
如何盡量處理TIMEWAIT過多?
編輯內核文件/etc/sysctl.conf,加入以下內容:
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 時間
然后執行 /sbin/sysctl -p 讓參數生效.
/etc/sysctl.conf是一個允許改變正在運行中的Linux系統的接口,它包含一些TCP/IP堆棧和虛擬內存系統的高級選項,修改內核參數永久生效。
簡單來說,就是打開系統的TIMEWAIT重用和快速回收。
如果以上配置調優后性能還不理想,可繼續修改一下配置:
vi /etc/sysctl.conf 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套接字拖死。
讀到這里,這篇“TIME_WAIT過多造成的問題如何解決”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。