終于搞懂了服務(wù)器為啥產(chǎn)生大量的TIME_WAIT!
原文鏈接:http://ningg.top/computer-basic-theory-tcp-time-wait
從這幾個(gè)方面著手:
問(wèn)題描述:什么現(xiàn)象?什么影響?
問(wèn)題分析
解決方案
底層原理

一部分 TIME_WAIT 連接被回收,但新的 TIME_WAIT 連接產(chǎn)生;
一些極端情況下,會(huì)出現(xiàn)大量的 TIME_WAIT 連接。
1.每一個(gè) time_wait 狀態(tài),都會(huì)占用一個(gè)「本地端口」,上限為 65535(16 bit,2 Byte);
2.當(dāng)大量的連接處于 time_wait 時(shí),新建立 TCP 連接會(huì)出錯(cuò),address already in use : connect 異常
// 統(tǒng)計(jì):各種連接的數(shù)量
$ netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
ESTABLISHED 1154
TIME_WAIT 16452、問(wèn)題分析
1.大量的短連接存在
2.特別是 HTTP 請(qǐng)求中,如果 connection 頭部取值被設(shè)置為 close 時(shí),基本都由「服務(wù)端」發(fā)起主動(dòng)關(guān)閉連接
3.而,TCP 四次揮手關(guān)閉連接機(jī)制中,為了保證 ACK 重發(fā)和丟棄延遲數(shù)據(jù),設(shè)置 time_wait 為 2 倍的 MSL(報(bào)文最大存活時(shí)間)
1.TCP 連接中,主動(dòng)關(guān)閉連接的一方出現(xiàn)的狀態(tài);(收到 FIN 命令,進(jìn)入 TIME_WAIT 狀態(tài),并返回 ACK 命令) 2.保持 2 個(gè) MSL 時(shí)間,即,4 分鐘;(MSL 為 2 分鐘)
3、解決辦法
TCP 連接中,「主動(dòng)發(fā)起關(guān)閉連接」的一端,會(huì)進(jìn)入 time_wait 狀態(tài) time_wait 狀態(tài),默認(rèn)會(huì)持續(xù) 2 MSL(報(bào)文的最大生存時(shí)間),一般是 2x2 mins time_wait 狀態(tài)下,TCP 連接占用的端口,無(wú)法被再次使用 TCP 端口數(shù)量,上限是 6.5w(65535,16 bit) 大量 time_wait 狀態(tài)存在,會(huì)導(dǎo)致新建 TCP 連接會(huì)出錯(cuò),address already in use : connect 異常
服務(wù)器端,一般設(shè)置:不允許「主動(dòng)關(guān)閉連接」 但 HTTP 請(qǐng)求中,http 頭部 connection 參數(shù),可能設(shè)置為 close,則,服務(wù)端處理完請(qǐng)求會(huì)主動(dòng)關(guān)閉 TCP 連接 現(xiàn)在瀏覽器中, HTTP 請(qǐng)求 connection 參數(shù),一般都設(shè)置為 keep-alive Nginx 反向代理場(chǎng)景中,可能出現(xiàn)大量短鏈接,服務(wù)器端,可能存在
3.解決辦法:
服務(wù)器端允許 time_wait 狀態(tài)的 socket 被重用 縮減 time_wait 時(shí)間,設(shè)置為 1 MSL(即,2 mins)
4、附錄 - 底層原理
附錄 A:查詢(xún) TCP 連接狀態(tài)
// Mac 下,查詢(xún) TCP 連接狀態(tài)
$ netstat -nat |grep TIME_WAIT
// Mac 下,查詢(xún) TCP 連接狀態(tài),其中 -E 表示 grep 或的匹配邏輯
$ netstat -nat | grep -E "TIME_WAIT|Local Address"
Proto Recv-Q Send-Q Local Address Foreign Address (state)
tcp4 0 0 127.0.0.1.1080 127.0.0.1.59061 TIME_WAIT
// 統(tǒng)計(jì):各種連接的數(shù)量
$ netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
ESTABLISHED 1154
TIME_WAIT 1645附錄 B:MSL 時(shí)間
當(dāng)TCP的一端發(fā)起主動(dòng)關(guān)閉(收到 FIN 請(qǐng)求),在發(fā)出最后一個(gè)ACK 響應(yīng)后,即第3次握 手完成后,發(fā)送了第四次握手的ACK包后,就進(jìn)入了TIME_WAIT狀態(tài)。
2.必須在此狀態(tài)上停留兩倍的MSL時(shí)間,等待2MSL時(shí)間主要目的是怕最后一個(gè) ACK包對(duì)方?jīng)]收到,那么對(duì)方在超時(shí)后將重發(fā)第三次握手的FIN包,主動(dòng)關(guān)閉端接到重發(fā)的FIN包后,可以再發(fā)一個(gè)ACK應(yīng)答包。
3.在 TIME_WAIT 狀態(tài)時(shí),兩端的端口不能使用,要等到2MSL時(shí)間結(jié)束,才可繼續(xù)使用。(IP 層)
4.當(dāng)連接處于2MSL等待階段時(shí),任何遲到的報(bào)文段都將被丟棄。
附錄 C:TCP 三次握手和四次握手

RE:time_wait 是「主動(dòng)關(guān)閉 TCP 連接」一方的狀態(tài),可能是「客服端」的,也可能是「服務(wù)器端」的; 一般情況下,都是「客戶(hù)端」所處的狀態(tài);「服務(wù)器端」一般設(shè)置「不主動(dòng)關(guān)閉連接」。
2. 服務(wù)器在對(duì)外服務(wù)時(shí),是「客戶(hù)端」發(fā)起的斷開(kāi)連接?還是「服務(wù)器」發(fā)起的斷開(kāi)連接?
正常情況下,都是「客戶(hù)端」發(fā)起的斷開(kāi)連接;
「服務(wù)器」一般設(shè)置為「不主動(dòng)關(guān)閉連接」,服務(wù)器通常執(zhí)行「被動(dòng)關(guān)閉」;
但 HTTP 請(qǐng)求中,http 頭部 connection 參數(shù),可能設(shè)置為 close,則,服務(wù)端處理完請(qǐng)求會(huì)主動(dòng)關(guān)閉 TCP 連接,
- END -
推薦閱讀 31天拿下K8s含金量最高的CKA+CKS證書(shū)! Kubernetes 網(wǎng)絡(luò)方案之炫酷的 Cilium Prometheus+InfluxDB+Grafana 打造高逼格監(jiān)控平臺(tái) 民生銀行 IT運(yùn)維故障管理 可視化案例 Kubernetes YAML 學(xué)習(xí),提升編寫(xiě)能力 這些 K8S 日常故障處理集錦,運(yùn)維請(qǐng)收藏~ 豬八戒網(wǎng) CI/CD 最佳實(shí)踐之路 從零開(kāi)始搭建創(chuàng)業(yè)公司DevOps技術(shù)棧 快、狠、準(zhǔn)!系統(tǒng)有效的排查運(yùn)維類(lèi)故障 12年資深運(yùn)維老司機(jī)的成長(zhǎng)感悟 搭建一套完整的企業(yè)級(jí) K8s 集群(v1.20,二進(jìn)制方式)
點(diǎn)亮,服務(wù)器三年不宕機(jī)


