連起來很慢! 慢在哪? - 網路延遲的小知識

smalltown
Starbugs Weekly 星巴哥技術專欄
12 min readSep 1, 2020

Background

網路對於提供線上服務應用程式的重要性當然是不言而諭,因此要如何監控也是個相當耗費心力的問題,因為一般的內部監控並無法滿足此需求,很多大家耳熟能詳的監控工具,例如:Prometheus,SkyWalking,Zabbix…等,都是架設在內部網路 (Intranet) 從內部來進行監控,跟來自於世界各地的一般使用者是完全不同的出發點,所以會有監控上的盲點,看著綠油油的 Dashboard 想說一切都好好的啊!但真實使用者卻已經火冒三丈,客服電話也已經被打到滿線

這種情形就會需要外部的監控服務來模擬一般使用者行為,用以確保服務是否在正常運作中,而在外部網路的監控中,通常會有哪一些重點需要注意,遇到問題的時候又該如何找出癥結點,便是這篇文章想要分享的內容

Resource Timing

在開始提到網路監控之前,先來看看當一個使用者發出 HTTP 請求時,到底經過了哪一些歷程,如此一來,我們才能夠知道所需要注意的重點有哪一些

Redirect: 請求是否需要被重新導向,耗費的時間當然就是從 redirect 開始到結束

App Cache: 要是 Client 在本地端已經有暫存的話,那請求的內容就可以直接從本地端讀取,不用再耗費網路資源

DNS Lookup: 網路世界的溝通通常都會使用網址,而不會直接使用 IP 位址,所以一定有透過 DNS Server 查找真實 IP 位址的需求,耗費的時間就是從查詢開始到取得結果的時間

TCP Connect: 跟查詢到的目標伺服器建立 TCP 連線所需要的時間,不過需要特別注意假如要建立的是 TLS 或是 SSL 的安全加密連線的話,這邊還會有 handshake 的發生

Request: 進行到 Request 階段,就是請求被發送到伺服器端所需要的時間

Response: 這個階段的時間就是遠端伺服器將結果回傳給提出請求 Client 的時間

看完上面之後,可以發現要建立一個 HTTP 的連線要經過很多的步驟 ,在成功收到回應之前,必須要跟遠端的伺服器來來回回,因此任何一個階段中 Client 和 Server 的連線出了問題,或是需要的時間變長了,都可能會導致應用程式出現不預期的結果

Common Network Issue

所以當今天突然從外部監控服務收到告警時,但是內部監控系統都還好好的,就可以開始從上面提到的每個階段來看看問題可能是出在哪邊,不過在開始找尋問題之前,有一件很重要的事情要先做!確保自己使用的網路環境跟真實使用者一樣的!例如: hosts 檔案是乾淨的沒有亂改過,不是使用可以連接到 intranet 的網路環境…等,不然還是會跟內部監控一樣地遇到盲點

DNS Lookup

首先一定要試試看,可不可以解析的到請求網址的 IP 位址,因為搞不好就是 DNS 設定錯誤導致連線失敗,下面是用 google.com 當作範例,可以看到去 8.8.8.8 DNS Server 後有問到 google.com 的 IP 位址,當查詢出來的結果有符合預期的話,那表示問題不在這邊,讓我們繼續往下找,不然就要去看看 DNS Record 哪裡設定錯誤了

# 查找成功
~$ nslookup google.com 8.8.8.8
Server: 8.8.8.8
Address: 8.8.8.8#53
Non-authoritative answer:
Name: google.com
Address: 216.58.200.238
# 查找失敗
> nslookup google.com 8.8.8.8
Server: 8.8.8.8
Address: 8.8.8.8#53
** server can't find google.com: NXDOMAIN

Telnet Service Port

接下來要懷疑到會不會是防火牆的設定有問題,假設服務開啟的 Port 是 443好了,底下一樣以 Google 來當作範例,使用 telnet 的話應該可以發現連線可以被建立成功

# 連線成功
~$ telnet google.com 443
Trying 172.217.27.142...
Connected to google.com.
Escape character is '^]'.
# 連線失敗
~$ telnet google.com 443
Trying 172.217.27.142...

遇到連線失敗的話,通常是防火牆端設定有問題,可以先檢查看看 Port 443 是否真的有對外開啟;而現在的外部監控服務通常都可以從多個區域同時監控,因此假如發現只有某一個或是某些區域遇到連線問題,就可以懷疑到 CDN 的設定,是不是有阻擋掉某一個區域,或是在防火牆上沒有允許某個區域的 CDN Edge 過來進行連線

SSL Certificate

上面進行 TCP 連線階段時,有提到想要建立的是安全連線的話,會進行 SSL Handshake,所以連線失敗也有可能是憑證發生問題,譬如常見問題就是遇到憑證過期了 (現在憑證越來越多,而且可以購買的期限越來越短,真的需要小心應對XD),而現在外部監控服務,其實也都有檢查憑證是否過期的功能,記得要把他設定起來

# 用 ClI 查詢網站的憑證有效期限
cho | openssl s_client -servername www.google.com -connect www.google.com:443 2>/dev/null | openssl x509 -noout -dates
notBefore=Aug 11 08:59:33 2020 GMT
notAfter=Nov 3 08:59:33 2020 GMT

Network Latency Issue

上面是比較常見的一些錯誤,都是完全無法連線且跟應用程式不相關的情況,但要是收到的告警是回應時間過長了,又該如何查出問題在哪裡呢?但在開始找問題之前,可以先到 https://wondernetwork.com/pings 這個網站瞧一瞧,因為網路的速度對於地理上的位置/線路來說是影響很大的,自己的服務架設在哪裏,而監控的區域/實際使用者又落在在哪個地方,他們之間的網路延遲時間基本消費是多少,可以先在這個網站查到,讓自己的心裡有個底

Chrome DevTools

最簡略又好用的分析問題工具,就是大家電腦都有安裝的 Chrome DevTools,他可以拿來分析網路連線時每個階段耗費的時間 (Queueing & Stalled 是指開始執行動作前的等待時間,跟網路無關)

DNS Lookup: 查找真實 IP 位址時間應該都會落在 10 ms 以內,但超過的話,可以試試看一些縮短時間的作法,例如使用比較快的 DNS Provider,改變 DNS Cache 的 TTL,減少需要連線的 Domain,DNS Prefetching,使用 ANAME Records …等

SSL: SSL Handshake 所需要耗費的時間可能會落在 100 ms 左右,不過要是測試時看到超過正常值很多的誇張數值,就可以試著去查查看問題在哪邊

TTFB: 全名為 Time To First Byte,就是指 Client 跟 Server 端建立完連線後,收到第一個 Byte 所需要的時間,落在 100ms 以下算是滿快的,Google PageSpeed Insights 建議落在 200ms 以下,一般可能會落在 300~500 左右,但是超過 600 ms 可能就要注意了,要縮短時間的話,應用程式端有很多事情可以做,例如加快程式運行的速度,縮短資料庫查詢時間,增加 Cache 機制 (不過這些跟網路都沒有關係就是了);而為了讓傳遞回應的速度變快,可以透過使用 CDN 縮短 Client 和 Server 間的實體傳遞距離

Content Download: 則是從 Server 端接收回應所需要的時間,這一段也跟網路傳遞速度比較有關係,想當然爾可以透過 CDN 加速

Curl

喜歡使用 CLI 工具查找問題的人可以直接使用 Curl 即可,建立名稱為 curl-format.txt 的檔案,然後內容如底下所示

time_namelookup:  %{time_namelookup}s\n
time_connect: %{time_connect}s\n
time_appconnect: %{time_appconnect}s\n
time_pretransfer: %{time_pretransfer}s\n
time_redirect: %{time_redirect}s\n
time_starttransfer: %{time_starttransfer}s\n
----------\n
time_total: %{time_total}s\n

接著就可以使用 Curl 來獲取跟 Chrome DevTools 差不多的資訊,從各個階段所耗費的時間取得問題發生的主要原因是什麼

~$ curl -w "@curl-format.txt" -o /dev/null -s "https://www.google.com/"time_namelookup:  0.002076s
time_connect: 0.036773s
time_appconnect: 0.070130s
time_pretransfer: 0.070228s
time_redirect: 0.000000s
time_starttransfer: 0.113621s
----------
time_total: 0.114728s

MTR

在 Server 端什麼都沒有修改,而且內部監控也顯示回應時間正常,但從外部監控服務就是可以看到回應時間明顯變長,而且持續了兩三天以上,這時候就必須要請出 MTR 這個查找路由耗費時間的工具,然後把查詢的結果附在 Support Ticket 內了XD MTR 其實算是 Ping 跟 Traceroute/Tracert 兩個工具的合體,他會丟出數個 ICMP 封包給 Client 連線到 Server 間的所有 hop,因此可以從中得知很多有用的資訊

例如從上圖可以知道連去 Google 總共會經過 12 個 hop,封包都沒有遺失的現象,送出 10 個封包的回覆時間都相當的低,落在 10 ms 左右 (他會列出平均,最佳,最差和最後的時間值),而最後面一欄標準差則是用來判斷連線的穩定度

當觀察到前面三個 hop 漏封包的頻率很高或是花的時間特別久,那可能就是 Client 端的 ISP 比較有嫌疑,而假如是最後三個 hop 有問題的話,那就變成是 Server 端的 ISP 比較有嫌疑;而通常會建議取得雙向的 MTR 資訊 (從 Client 到 Server,以及從 Server 到 Client) 這樣分析問題起來比較準確

有一種現象是觀察到某一個 hop 漏封包的頻率衝高或是花的時間特別久,可以持續觀察一下他的下一個或是下幾個 hop 取得的數值是不是正常的,因為有時候可能只是某個 hop 有設定 Rate Limit,所以導致數值在他身上會飆高,但後續的 hop 又會恢復正常,這樣的情況很常見,而且是沒有問題的

Conclusion

網路問題百百種,此文章把一些自己個人常見的問題寫下來,除了當成自己的學習筆記之外,也希望可以不小心幫助到需要的人,不過當問題落在需要使用 MTR 的話,其實會花比較多時間,為什麼呢?

因為現在的網路服務通常都是 CDN 搭配上 Public Cloud Provider,甚至是其他的第三方服務, 假如 MTR 最後的 hop 落在 CDN ,Public Cloud 或是其他第三方服務的話,就要花比較多時間跟多間第三方廠商來來回回,有時會遇到自己這邊什麼事情都沒有做,但問題就突然自己解決了,最苦的是最後通常也不會找到真正的原因 ╮(╯_╰)╭ 只能猜測是 ISP 或是第三方廠商的 Network Team 把路由又改回原本正常的狀態了吧?!所以會建議等個兩三天之後,情況一直沒有改善再花時間去追問題

Reference

--

--

smalltown
Starbugs Weekly 星巴哥技術專欄

原來只是一介草 QA,但開始研究自動化維運雲端服務後,便一頭栽進 DevOps 的世界裏,熱愛鑽研各種可以提升雲端服務品質及增進團隊開發效率的開源技術