如何解決Tengine健康檢查引起的TIME_WAIT堆積問題

如何解決Tengine健康檢查引起的TIME_WAIT堆積問題,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

成都創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價(jià)比臨沂網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式臨沂網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋臨沂地區(qū)。費(fèi)用合理售后完善,10多年實(shí)體公司更值得信賴。

1. 問題背景

“服務(wù)上云后,我們的TCP端口基本上都處于TIME_WAIT的狀態(tài)”、“這個(gè)問題在線下機(jī)房未曾發(fā)生過” 這是客戶提交問題的描述。

客戶環(huán)境是自建Tengine作為7層反向代理,后端接約1.8萬臺(tái)NGINX。Tengine上云之后,在服務(wù)器上發(fā)現(xiàn)大量的TIME_WAIT狀態(tài)的TCP socket;由于后端較多,潛在可能影響業(yè)務(wù)可用性。用戶對(duì)比之前的經(jīng)驗(yàn)比較擔(dān)心是否可能是接入阿里云之后導(dǎo)致,所以希望我們對(duì)此進(jìn)行詳細(xì)的分析。

注:TIME_WAIT狀態(tài)的監(jiān)聽?zhēng)淼膯栴}在于主機(jī)無法為往外部的連接請(qǐng)求分配動(dòng)態(tài)端口。此時(shí),可以配置net.ipv4.ip_local_port_range,增加其端口選擇范圍(可以考慮 5000 - 65535),但依然存在 2 MSL 時(shí)間內(nèi)被用完的可能。

2. TIME_WAIT原因分析

首先,如果我們重新回顧下TCP狀態(tài)機(jī)就能知道,TIME_WAIT狀態(tài)的端口僅出現(xiàn)在主動(dòng)關(guān)閉連接的一方(跟這一方是客戶端或者是服務(wù)器端無關(guān))。當(dāng)TCP協(xié)議棧進(jìn)行連接關(guān)閉請(qǐng)求時(shí),只有【主動(dòng)關(guān)閉連接方】會(huì)進(jìn)入TIME_WAIT狀態(tài)。

而客戶的顧慮也在這里。

一方面,健康檢查使用 HTTP1.0 是短連接,邏輯上應(yīng)該由后端NGINX服務(wù)器主動(dòng)關(guān)閉連接,多數(shù)TIME_WAIT應(yīng)該出現(xiàn)在NGINX側(cè)。

另一方面,我們也通過抓包確認(rèn)了多數(shù)連接關(guān)閉的第一個(gè)FIN請(qǐng)求均由后端NGINX服務(wù)器發(fā)起,理論上,Tengine服務(wù)器的socket 應(yīng)該直接進(jìn)入CLOSED狀態(tài)而不會(huì)有這么多的TIME_WAIT 。
抓包情況如下,我們根據(jù)Tengine上是TIME_WAIT的socket端口號(hào),進(jìn)行了過濾。

如何解決Tengine健康檢查引起的TIME_WAIT堆積問題

圖1:一次HTTP請(qǐng)求交互過程

雖然上面的抓包結(jié)果顯示當(dāng)前 Tengine 行為看起來確實(shí)很奇怪,但實(shí)際上通過分析,此類情形在邏輯上還是存在的。為了解釋這個(gè)行為,我們首先應(yīng)該了解:通過tcpdump抓到的網(wǎng)絡(luò)數(shù)據(jù)包,是該數(shù)據(jù)包在該主機(jī)上收發(fā)的“結(jié)果”。盡管在抓包上看,Tengine側(cè)看起來是【被動(dòng)接收方】角色,但在操作系統(tǒng)中,這個(gè)socket是否屬于主動(dòng)關(guān)閉的決定因素在于操作系統(tǒng)內(nèi)TCP協(xié)議棧如何處理這個(gè)socket。

針對(duì)這個(gè)抓包分析,我們的結(jié)論就是:可能這里存在一種競(jìng)爭(zhēng)條件(Race Condition)。如果操作系統(tǒng)關(guān)閉socket和收到對(duì)方發(fā)過來的FIN同時(shí)發(fā)生,那么決定這個(gè)socket進(jìn)入TIME_WAIT還是CLOSED狀態(tài)決定于 主動(dòng)關(guān)閉請(qǐng)求(Tengine 程序針對(duì) socket 調(diào)用 close 操作系統(tǒng)函數(shù))和 被動(dòng)關(guān)閉請(qǐng)求(操作系統(tǒng)內(nèi)核線程收到 FIN 后調(diào)用的 tcp_v4_do_rcv 處理函數(shù))哪個(gè)先發(fā)生 。

很多情況下,網(wǎng)絡(luò)時(shí)延,CPU處理能力等各種環(huán)境因素不同,可能帶來不同的結(jié)果。例如,而由于線下環(huán)境時(shí)延低,被動(dòng)關(guān)閉可能最先發(fā)生;自從服務(wù)上云之后,Tengine跟后端Nginx的時(shí)延因?yàn)榫嚯x的原因被拉長(zhǎng)了,因此Tengine主動(dòng)關(guān)閉的情況更早進(jìn)行,等等,導(dǎo)致了云上云下不一致的情況。

可是,如果目前的行為看起來都是符合協(xié)議標(biāo)準(zhǔn)的情況,那么如何正面解決這個(gè)問題就變得比較棘手了。我們無法通過降低Tengine所在的主機(jī)性能來延緩主動(dòng)連接關(guān)閉請(qǐng)求,也無法降低因?yàn)槲锢砭嚯x而存在的時(shí)延消耗加快 FIN 請(qǐng)求的收取。這種情況下,我們會(huì)建議通過調(diào)整系統(tǒng)配置來緩解問題。

注:現(xiàn)在的Linux系統(tǒng)有很多方法都可以快速緩解該問題,例如:

a) 在timestamps啟用的情況下,配置tw_reuse。
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_timestamps = 1
b) 配置 max_tw_buckets
net.ipv4.tcp_max_tw_buckets = 5000
缺點(diǎn)就是會(huì)往syslog里寫: time wait bucket table overflow.

由于用戶使用自建 Tengine ,且用戶不愿意進(jìn)行 TIME_WAIT 的強(qiáng)制清理,因此我們考慮通過Tengine的代碼分析看看是否有機(jī)會(huì)在不改動(dòng) Tengine 源碼的情況下,改變 Tengine 行為來避免socket被Tengine主動(dòng)關(guān)閉。
Tengine version: Tengine/2.3.1
NGINX version: nginx/1.16.0

2.1 Tengine code analysis

從之前的抓包,我們可以看出來多數(shù)的TIME_WAIT socket是為了后端健康檢查而創(chuàng)建的,因此我們主要關(guān)注 Tengine的健康檢查行為,以下是從ngx_http_upstream_check_module 的開源代碼中摘抄出來的關(guān)于socket清理的函數(shù)。

如何解決Tengine健康檢查引起的TIME_WAIT堆積問題

圖2:Tengine 健康檢查完成后清理socket過程

從這段邏輯中,我們可以看到,如果滿足以下任一條件時(shí),Tengine會(huì)在收到數(shù)據(jù)包之后直接關(guān)閉連接。

  • c->error != 0

  • cf->need_keepalive = false

  • c->requests > ucscf->check_keepalive_requ

如何解決Tengine健康檢查引起的TIME_WAIT堆積問題

圖3: Tengine 中真正完成socket關(guān)閉的函數(shù)

這里,如果我們讓以上的條件變成不滿足,那么就有可能讓Tengine所在的操作系統(tǒng)先處理被動(dòng)關(guān)閉請(qǐng)求,進(jìn)行socket清理,進(jìn)入CLOSED狀態(tài),因?yàn)閺腍TTP1.0的協(xié)議上來說,NGINX服務(wù)器這一方一定會(huì)主動(dòng)關(guān)閉連接。

2.2 解決方法

一般情況下,我們對(duì)于TIME_WAIT的連接無需太過關(guān)心,一般2MSL(默認(rèn)60s) 之后,系統(tǒng)自動(dòng)釋放。如果需要減少,可以考慮長(zhǎng)鏈接模式,或者調(diào)整參數(shù)。

該case中,客戶對(duì)協(xié)議比較了解,但對(duì)于強(qiáng)制釋放TIME_WAIT 仍有擔(dān)心;同時(shí)由于后端存在1.8萬臺(tái)主機(jī),長(zhǎng)連接模式帶來的開銷更是無法承受。

因此,我們根據(jù)之前的代碼分析,通過梳理代碼里面的邏輯,推薦客戶以下健康檢查配置:

check interval=5000 rise=2 fall=2 timeout=3000 type=http default_down=false;
check_http_send "HEAD / HTTP/1.0\r\n\r\n";
check_keepalive_requests 2
check_http_expect_alive http_2xx http_3xx;
理由很簡(jiǎn)單,我們需要讓之前提到的三個(gè)條件不滿足。在代碼中,我們不考慮 error 情況,而need_keepalive 在代碼中默認(rèn) enable (如果不是,可以通過配置調(diào)整),因此需確保check_keepalive_requests大于1即可進(jìn)入Tengine的KEEPALIVE邏輯,避免Tengine主動(dòng)關(guān)閉連接。

如何解決Tengine健康檢查引起的TIME_WAIT堆積問題

圖4:Tengine健康檢查參考配置

因?yàn)槭褂肏TTP1.0的HEAD方法,后端服務(wù)器收到后會(huì)主動(dòng)關(guān)閉連接,因此Tengine創(chuàng)建的socket進(jìn)入CLOSED狀態(tài),避免進(jìn)入TIME_WAIT而占用動(dòng)態(tài)端口資源。

看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對(duì)創(chuàng)新互聯(lián)的支持。

網(wǎng)站題目:如何解決Tengine健康檢查引起的TIME_WAIT堆積問題
文章源于:http://bm7419.com/article12/igdjgc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)建站、品牌網(wǎng)站設(shè)計(jì)、App開發(fā)、自適應(yīng)網(wǎng)站、電子商務(wù)、面包屑導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

綿陽服務(wù)器托管