前言

兩條豎線分別是表示:
- 主動關閉(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
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/379054.html
標籤:Java
上一篇:突發!Apache Log4j2 報核彈級漏洞。。趕緊修復!!
下一篇:演算法高級學習2
