也说说TIME_WAIT状态
也說說TIME_WAIT狀態
一個朋友問到,自己用go寫了一個簡單的HTTP服務端程序,為什么壓測的時候服務端會出現一段時間的TIME_WAIT超高的情況,導致壓測的效果不好呢?
記得老王有兩篇文章專門說這個,當時粗粗看了一遍,正好碰上這個問題,又翻出來細細摟了。
第一個要弄懂的,是TIME_WAIT是怎么產生的。
TIME_WAIT狀態是怎么產生的
要弄懂TIME_WAIT要從TCP的四次握手的分手協議說起。
上面這個圖片展示了TCP從連接建立到連接釋放的過程中,客戶端和服務端的狀態變化圖。如果只看連接釋放階段,四次握手
客戶端先發送FIN,進入FIN_WAIT1狀態
服務端收到FIN,發送ACK,進入CLOSE_WAIT狀態,客戶端收到這個ACK,進入FIN_WAIT2狀態
服務端發送FIN,進入LAST_ACK狀態
客戶端收到FIN,發送ACK,進入TIME_WAIT狀態,服務端收到ACK,進入CLOSE狀態
客戶端TIME_WAIT持續2倍MSL時長,在linux體系中大概是60s,轉換成CLOSE狀態
當然在這個例子和上面的圖片中,使用客戶端和服務端來描述是不準確的,TCP主動斷開連接的一方可能是客戶端,也可能是服務端。所以使用主動斷開的一方,和被動斷開的一方替換上面的圖可能更為貼切。
不管怎么說,TIME_WAIT的狀態就是主動斷開的一方,發送完最后一次ACK之后進入的狀態。并且持續時間還挺長的。
能不能發送完ACK之后不進入TIME_WAIT就直接進入CLOSE狀態呢?不行的,這個是為了TCP協議的可靠性,由于網絡原因,ACK可能會發送失敗,那么這個時候,被動一方會主動重新發送一次FIN,這個時候如果主動方在TIME_WAIT狀態,則還會再發送一次ACK,從而保證可靠性。那么從這個解釋來說,2MSL的時長設定是可以理解的,MSL是報文最大生存時間,如果重新發送,一個FIN+一個ACK,再加上不定期的延遲時間,大致是在2MSL的范圍。
所以從理論上說,網上調試參數降低TIME_WAIT的持續時間的方法是一種以可靠性換取性能的一種方式。嗯,質量守恒定理還是鐵律。
服務端TIME_WAIT過多
回到上面的問題,go寫了一個HTTP服務,壓測發現TIME_WAIT過多。
首先判斷是不是壓測程序放在服務的同一臺機器...當然不會犯這么低級的錯誤...
那么這個感覺就有點奇怪了,HTTP服務并沒有依賴外部mysql或者redis等服務,就是一個簡單的Hello world,而TIME_WAIT的是主動斷開方才會出現的,所以主動斷開方是服務端?
答案是是的。在HTTP1.1協議中,有個 Connection 頭,Connection有兩個值,close和keep-alive,這個頭就相當于客戶端告訴服務端,服務端你執行完成請求之后,是關閉連接還是保持連接,保持連接就意味著在保持連接期間,只能由客戶端主動斷開連接。還有一個keep-alive的頭,設置的值就代表了服務端保持連接保持多久。
HTTP默認的Connection值為close,那么就意味著關閉請求的一方幾乎都會是由服務端這邊發起的。那么這個服務端產生TIME_WAIT過多的情況就很正常了。
雖然HTTP默認Connection值為close,但是現在的瀏覽器發送請求的時候一般都會設置Connection為keep-alive了。所以,也有人說,現在沒有必要通過調整參數來使TIME_WAIT降低了。
解決方法
按照HTTP協議的頭,我們在壓測程序發出的HTTP協議頭里面加上connection:keep-alive當然能解決這個問題。
還有的方法就是系統參數調優:
sysctl?net.ipv4.tcp_tw_reuse=1sysctl?net.ipv4.tcp_tw_recycle=1sysctl?net.ipv4.tcp_timestamps=1tcp_tw_reuse
這個參數作用是當新的連接進來的時候,可以復用處于TIME_WAIT的socket。默認值是0。
tcp_tw_recycle和tcp_timestamps
默認TIME_WAIT的超時時間是2倍的MSL,但是MSL一般會設置的非常長。如果tcp_timestamps是關閉的,開啟tcp_tw_recycle是沒用的。但是一般情況下tcp_timestamps是默認開啟的,所以直接開啟就有用了。
參考文章
記一次TIME_WAIT網絡故障
再敘TIME_WAIT
Time-wait狀態(2MSL)一些理解
tcp_tw_recycle和tcp_timestamps導致connect失敗問題
https://blog.csdn.net/tmq1225/article/details/52183216
原文參考:https://www.cnblogs.com/yjf512/p/5327886.html
轉載于:https://blog.51cto.com/tenderrain/2116058
總結
以上是生活随笔為你收集整理的也说说TIME_WAIT状态的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 『Python底层原理』--Python
- 下一篇: hgame2025-Crypto小记