tcp 連接 time-wait 狀態過多問題解釋

前言

兩條豎線分別是表示:

  • 主動關閉(active close)的一方
  • 被動關閉(passive close)的一方

網絡上類似的圖有很多,但是有的細節不夠,有的存在誤導。有的會把兩條線分別標記成 client 和 server。給讀者造成困惑。對於斷開連接這件事,客戶端和服務端都能作爲主動方發起,也就是 active close 可以是客戶端,也可以是服務端。而對端相應的就是 passive close。不管誰發起,狀態遷移如上圖。

問題描述

模擬高併發的場景,會出現批量的 time-wait 的 tcp 連接:

短時間後,所有的 time-wait 全都消失,被回收,端口包括服務,均正常。即,在高併發的場景下,time-wait 連接存在,屬於正常現象。

線上場景中,持續的高併發場景:

  • 一部分 time-wait 連接被回收,但新的 time-wait 連接產生;
  • 一些極端情況下,會出現大量的 time-wait 連接;

所以,上述大量的 time-wait 狀態 tcp 連接,有什麼業務上的影響嗎?

Nginx 作爲反向代理時,大量的短鏈接,可能導致 Nginx 上的 tcp 連接處於 time_wait 狀態:

  • 每一個 time_wait 狀態,都會佔用一個本地端口,上限爲 65535(16 bit,2 Byte);
  • 當大量的連接處於 time_wait 時,新建立 tcp 連接會出錯,address already in use : connect 異常;

統計 tcp 連接的狀態:

// 統計:各種連接的數量
$ netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
ESTABLISHED 1154
TIME_WAIT 1645

tips: tcp 本地端口數量,上限爲 65535 ,這是因爲 tcp 頭部使用 16 bit 存儲端口號,因此約束上限爲 65535。

問題分析

大量的 time-wait 狀態 tcp 連接存在,其本質原因是什麼?

  • 大量的短連接存在;
  • 特別是 HTTP 請求中,如果 connection 頭部取值被設置爲 close 時,基本都由服務端發起主動關閉連接;
  • tcp 四次揮手關閉連接機制中,爲了保證 ACK 重發和丟棄延遲數據,設置 time_wait 爲 2 倍的 MSL(報文最大存活時間);

time-wait 狀態:

  • tcp 連接中,主動關閉連接的一方出現的狀態;(收到 FIN 命令,進入 time-wait 狀態,並返回 ACK 命令)
  • 保持 2 個 MSL 時間,即 4 分鐘;(MSL 爲 2 分鐘)

解決辦法

解決上述 time_wait 狀態大量存在,導致新連接創建失敗的問題,一般解決辦法:

  • 客戶端,HTTP 請求的頭部,connection 設置爲 keep-alive,保持存活一段時間,現在的瀏覽器,一般都這麼進行了;
  • 服務器端,允許 time_wait 狀態的 socket 被重用;
  • 服務器端,縮減 time_wait 時間,設置爲 1 MSL;(即 2 分鐘)

順便提一嘴服務端出現大量 close_wait 的原因。多是由於服務端處理請求耗時過長,導致客戶端超時,發起關閉鏈接,導致服務端大量的 close_wait。



參考鏈接:https://www.zhihu.com/question/298214130

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