【tcp】RT 過長,排查思路

大多數(shù)人應(yīng)該聽過一道經(jīng)典的面試題:請詳細(xì)地說出從瀏覽器地址欄輸入 url 到最終呈現(xiàn)出結(jié)果的過程,越詳細(xì)越好,為什么面試官這么喜歡問這道題呢,因為這個題涉及的面非常廣,知識點非常多,如果你能完全吃透,非常有助于排查一些疑難雜癥。

今天我要分享的這個 case 就是個典型,廢話不多說,進(jìn)入正題。

前端同學(xué)發(fā)現(xiàn)新開發(fā)的項目接口有 1/3 概率出現(xiàn) RTT(請求往返時間)大于 3 s 的情況,以登錄接口為例,Chrome 請求所花時間如下:

image

正常的 RTT 在幾十 ms 左右,所以 3s 這個時延肯定不正常,于是著手排查,由于每個接口都可能超過 3s,所以下文皆以登錄接口分析為例,因為登錄接口邏輯相對比較簡單。

  1. 排除瀏覽器本身的問題

估計大家看到這種問題馬上就斷定是 server 的問題,立馬開始著手排查 server 的問題,不急,我們要先把瀏覽器本身可能導(dǎo)致請求緩慢的問題給排除了,瀏覽器本身可能因為「請求最大并發(fā)數(shù)量限制」,「更高優(yōu)先級的請求插隊,低優(yōu)先級的任務(wù)被延后」等原因?qū)е抡埱缶徛?/p>

為了排除瀏覽器本身造成的網(wǎng)絡(luò)請求過慢,我們最好找一個其它的瀏覽器比如 Safari 或者終端 curl 請求來再重試下這個請求,看下請求是否依然緩慢,這里我兩個方法都試了,用 Safari 也重現(xiàn)了 RTT 大于 3s 的情況。

用 curl 在終端請求也發(fā)現(xiàn)了 RTT 大于 3s 的情況,如何使用 curl 請求呢,這里提醒一下,大家千萬不要傻傻地去構(gòu)建一個 curl 請求,瀏覽器的網(wǎng)絡(luò)請求本身可以導(dǎo)出成 curl 的形式的,在「network」中點擊網(wǎng)絡(luò)請求,選中「Copy as cURL」,就可獲取此請求的 curl 表示方式

image

獲得 curl 請求后,對此請求稍加改造,加上如下 -o,-s, -w 選項

$ curl -o /dev/null -s -w  \
"time_connect: %{time_connect} \n \
 time_starttransfer: %{time_starttransfer} \n \
 time_nslookup:%{time_namelookup} \n \
time_total: %{time_total} \n" \
https://www.example.com

這里對幾個參數(shù)簡要作下說明:
-o /dev/null 屏蔽原有輸出信息,-s 靜默模式,不輸出任何東西,-w %{http_code} 控制額外輸出。

請求后會出現(xiàn)類似以下的結(jié)果

time_connect: 0.045897
time_starttransfer: 3.064762
time_nslookup:0.004328
time_total: 3.064777

前面幾個參數(shù)就不多做說明了,一般我們只要關(guān)心最后一個 time_total 參數(shù)即可,表示請求花費的全部時間。

從流量的流轉(zhuǎn)路徑著手了,客戶端發(fā)出請求要經(jīng)過哪些流程才能到達(dá)后端服務(wù)?

image.png

可以看到請求需要經(jīng)過反向代理層,接入層后才能到達(dá)我們的站點層(即我們的 Spring MVC 服務(wù)),也就是說從「反向代理層到接入層」及「接入層到站點層」都可能導(dǎo)致請求緩慢,于是我把我用 arthas trace 執(zhí)行的結(jié)果(MVC 服務(wù)執(zhí)行時間 80ms 左右)與前端請求有 1/3 的概率超過 3s 的結(jié)論告訴了運維,讓他們排查一下從反向代理層到站點層這中間是否有啥問題,不一會兒果然查出了問題。

結(jié)論是這樣的:本來 MVC 服務(wù)的機(jī)器有三臺,后來縮容了一臺,變成了兩臺,但接入層 kongfu 依然持有這臺被縮容的機(jī)器 ip,沒有將其踢掉,所以前端流量打進(jìn)來后,由于接入層的負(fù)載均衡策略,請求是有 1/3 的概率打到這臺下線機(jī)器的 ip 上的,由于這個 ip 對應(yīng)的機(jī)器無法響應(yīng)這個請求,等到超時后,kongfu 會重試把這個請求打到另外正常的兩臺機(jī)器中的任意一臺,也就是說請求 3s 中的大部分時間花在了等待那臺不正常的 ip 機(jī)器響應(yīng)上了。

image.png

有人可能會問,機(jī)器被踢掉了,接入層 kongfu 應(yīng)該是能檢測其下線的吧,怎么還會給這臺下線的機(jī)器發(fā)請求呢?

是的,kongfu 會通過端口檢測來檢測機(jī)器是否存活的,但問題是,這臺被縮容的機(jī)器雖然被回收了,但它的 ip 也是可以重新被分配給其他機(jī)器的,這種情況下 kongfu 通過端口檢測就會認(rèn)為它持有的 ip 對應(yīng)的機(jī)器是存活的,而這臺被分配此 ip 的機(jī)器又剛好不是 Spring MVC 服務(wù),那正常 MVC 請求打給它的話,它就無法處理了,只能等到請求超時再由 kongfu 重試轉(zhuǎn)發(fā)給正常的機(jī)器。

有人可能會好奇,運維是怎么查出來的呢,通過 「curl -I www.example」的形式可以輸出開頭信息,然后加上 -b 選項可以帶上 cookie,我們的接入層如果發(fā)現(xiàn)請求里帶有某些特殊的 cookie 會返回一個名為「X-KF-Via」的頭字段,如下:

X-KF-Via: agw(bip=10.65.x.1:8001,10.65.x.2:8001;b=mvc_service)

這個頭字段表示,請求 mvc_service 服務(wù)總共請求了兩臺機(jī)器,第一臺 10.65.x.1 未成功后,再接著重試 10.65.x.2:8001,所以由此可以排查出 10.65.x.1 這臺機(jī)器有問題,所以你看熟悉系統(tǒng)架構(gòu)有多重要,如果我早知道有這么一個選項,就可以一步到位排查出此問題了.

知道了問題所在,處理方案就很簡單了,直接把這臺有問題的機(jī)器從 kongfu 摘掉就行了!

排查的思路其實相對比較清晰,但一定要對請求的整個流轉(zhuǎn)流程有一個比較清醒的認(rèn)識,這樣才能快速判斷出問題所在,現(xiàn)在再回頭看下開頭的那道經(jīng)典面試題「請詳細(xì)地說出從瀏覽器地址欄輸入 url 到最終呈現(xiàn)出結(jié)果的過程,越詳細(xì)越好」,相信你會頗有感觸,這道面試題如果你對請求流轉(zhuǎn)的每個點都吃透得話,將極大地提升你排查解決問題的能力,舉個例子,之前就有人反饋這樣的一個問題:

在做 Server 壓力測試時發(fā)現(xiàn),客戶端給服務(wù)器不斷發(fā)請求,并接受服務(wù)器端的響應(yīng)。
發(fā)現(xiàn)接收服務(wù)器響應(yīng)的過程中,會出現(xiàn) recv 服務(wù)器端響應(yīng),阻塞 40ms 的情況,但是查看 server 端日志,Server 都在 2ms 內(nèi)將請求處理完成,并給客戶端響應(yīng)

如果你了解 TCP,就知道它是由于 TCP 的延遲確認(rèn)機(jī)制和 Nagle 算法及擁塞控制導(dǎo)致的,自然而然就會朝著這個方向 去解決了,比如打開 TCP_NODELAY 選項等。

參考

RT 過長,排查思路
https://bestxf.blog.csdn.net/article/details/118193092

記錄線上RT規(guī)律性增長問題排查
http://www.itdecent.cn/p/0c0e5c438116

瀏覽器、 postman操作和curl命令互轉(zhuǎn)
http://www.itdecent.cn/p/a6310e0fd290

用curl查看http請求各階段響應(yīng)時間
http://www.itdecent.cn/p/1f6e21e75841

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容