當前位置:編程學習大全網 - 編程語言 - 服務產生大量TIME_WAIT如何解決

服務產生大量TIME_WAIT如何解決

當TIME_WAIT超過linux系統tw數量的閥值(可用數量不會大於65535),系統會把多余的time-wait socket?刪除掉,並且顯示警告信息,如果是NAT網絡環境又存在大量訪問,會產生各種連接不穩定斷開的情況,從而影響了服務的穩定性。

壹、狀態的產生

要解決TIME_WAIT狀態過多的問題,先來研究下TIME_WAIT狀態的產生,下面是TCP連接斷開時的四次揮手狀態轉換圖,說明壹點,途中顯示的是客戶端主動斷開連接,tcp連接也可以由服務器端主動斷開連接。我們先來描述壹下斷開的狀態:

1)客戶端進程發出連接釋放報文,並且停止發送數據。釋放數據報文首部,FIN=1,其序列號為seq=u(等於前面已經傳送過來的數據的最後壹個字節的序號加1),此時,客戶端進入FIN-WAIT-1(終止等待1)狀態。 TCP規定,FIN報文段即使不攜帶數據,也要消耗壹個序號。

2)服務器收到連接釋放報文,發出確認報文,ACK=1,ack=u+1,並且帶上自己的序列號seq=v,此時,服務端就進入了CLOSE-WAIT(關閉等待)狀態。TCP服務器通知高層的應用進程,客戶端向服務器的方向就釋放了,這時候處於半關閉狀態,即客戶端已經沒有數據要發送了,但是服務器若發送數據,客戶端依然要接受。這個狀態還要持續壹段時間,也就是整個CLOSE-WAIT狀態持續的時間。

3)客戶端收到服務器的確認請求後,此時,客戶端就進入FIN-WAIT-2(終止等待2)狀態,等待服務器發送連接釋放報文(在這之前還需要接受服務器發送的最後的數據)。

4)服務器將最後的數據發送完畢後,就向客戶端發送連接釋放報文,FIN=1,ack=u+1,由於在半關閉狀態,服務器很可能又發送了壹些數據,假定此時的序列號為seq=w,此時,服務器就進入了LAST-ACK(最後確認)狀態,等待客戶端的確認。

5)客戶端收到服務器的連接釋放報文後,必須發出確認,ACK=1,ack=w+1,而自己的序列號是seq=u+1,此時,客戶端就進入了TIME-WAIT(時間等待)狀態。註意此時TCP連接還沒有釋放,必須經過2MSL(最長報文段壽命,RFC規定壹個MSL為2min,linux中壹般設置為30s)的時間後,當客戶端撤銷相應的TCB後,才進入CLOSED狀態。

6)服務器只要收到了客戶端發出的確認,立即進入CLOSED狀態。同樣,撤銷TCB後,就結束了這次的TCP連接。可以看到,服務器結束TCP連接的時間要比客戶端早壹些。

可以看到TIME_WAIT狀態產生是在tcp連接主動關閉的壹端產生的正常tcp狀態,超過兩個MSL之後,就會關閉,釋放占用的端口。基於以上的分析我們可以推斷,在我們的應用中產生大量TIME_WAIT狀態的根本原因是頻繁創建斷開連接TCP連接。要解決TIME_WATIT狀態過多的問題,就要分析我們的應用把頻繁創建的短連接改為長連接。

二、常見的短連接產生的場景

1.服務連接服務

後臺業務服務器,通常需要調用redis、mysql以及其他http服務和grpc服務,在服務相互調用中,如果使用的是短連接,高並發時就會產生大量TIME_WAIT,如何解決呢?壹般情況下,redis等客戶端會有連接池,我們要做的是設置好相關的連接服用參數,壹般會有連接數、連接重用時間、連接空閑數等。所以在應用中通過設置合理的連接池參數可以避免TIME_WAIT狀態過多的問題:

1.檢查http連接池

2.檢查grpc連接池

3.檢查redis連接池

4.檢查mysql連接池

...

我們來查看壹個mysql連接池配置信息,最大連接數100,最大空閑連接數10,測試的並發數50,產生的效果如下:

可以看到TIME_WAIT狀態快速上升,我們查看redis客戶端的連接情況:

{MaxOpenConnections:100 OpenConnections:1 InUse:0 Idle:1 WaitCount:0 WaitDuration:0s MaxIdleClosed:0 MaxLifetimeClosed:0}

{MaxOpenConnections:100 OpenConnections:17 InUse:15 Idle:2 WaitCount:0 WaitDuration:0s MaxIdleClosed:48 MaxLifetimeClosed:0}

{MaxOpenConnections:100 OpenConnections:51 InUse:44 Idle:7 WaitCount:0 WaitDuration:0s MaxIdleClosed:82 MaxLifetimeClosed:0}

{MaxOpenConnections:100 OpenConnections:51 InUse:50 Idle:1 WaitCount:0 WaitDuration:0s MaxIdleClosed:90 MaxLifetimeClosed:0}

{MaxOpenConnections:100 OpenConnections:50 InUse:49 Idle:1 WaitCount:0 WaitDuration:0s MaxIdleClosed:126 MaxLifetimeClosed:0}

{MaxOpenConnections:100 OpenConnections:51 InUse:49 Idle:2 WaitCount:0 WaitDuration:0s MaxIdleClosed:131 MaxLifetimeClosed:0}

{MaxOpenConnections:100 OpenConnections:50 InUse:49 Idle:1 WaitCount:0 WaitDuration:0s MaxIdleClosed:181 MaxLifetimeClosed:0}

{MaxOpenConnections:100 OpenConnections:51 InUse:51 Idle:0 WaitCount:0 WaitDuration:0s MaxIdleClosed:233 MaxLifetimeClosed:0}

{MaxOpenConnections:100 OpenConnections:51 InUse:51 Idle:0 WaitCount:0 WaitDuration:0s MaxIdleClosed:240 MaxLifetimeClosed:0}

{MaxOpenConnections:100 OpenConnections:46 InUse:38 Idle:8 WaitCount:0 WaitDuration:0s MaxIdleClosed:296 MaxLifetimeClosed:0}

{MaxOpenConnections:100 OpenConnections:51 InUse:50 Idle:1 WaitCount:0 WaitDuration:0s MaxIdleClosed:313 MaxLifetimeClosed:0}

{MaxOpenConnections:100 OpenConnections:51 InUse:50 Idle:1 WaitCount:0 WaitDuration:0s MaxIdleClosed:363 MaxLifetimeClosed:0}

{MaxOpenConnections:100 OpenConnections:51 InUse:50 Idle:1 WaitCount:0 WaitDuration:0s MaxIdleClosed:409 MaxLifetimeClosed:0}

{MaxOpenConnections:100 OpenConnections:50 InUse:48 Idle:2 WaitCount:0 WaitDuration:0s MaxIdleClosed:438 MaxLifetimeClosed:0}

{MaxOpenConnections:100 OpenConnections:49 InUse:49 Idle:0 WaitCount:0 WaitDuration:0s MaxIdleClosed:494 MaxLifetimeClosed:0}

分析發現MaxIdleClosed數據持續上升,此為mysql客戶端連接池配置不合理產生大量TIME_WAIT狀態的例子

2.網絡抖動

? 網絡情況不好時,如果主動方無TIME_WAIT等待,關閉前個連接後,主動方與被動方又建立起新的TCP連接,這時被動方重傳或延時過來的FIN包過來後會直接影響新的TCP連接。同樣網絡情況不好並且無TIME_WAIT等待,關閉連接後無新連接,當接收到被動方重傳或延遲的FIN包後,會給被動方回壹個RST包,可能會影響被動方其它的服務連接。

網絡抖動問題比較好排查,直接使用ping命令可以觀察到。

  • 上一篇:小學六年級作文600字:做模型小汽車
  • 下一篇:開發網站需要什麽技術
  • copyright 2024編程學習大全網