連起來很慢! 慢在哪? - 網路延遲的小知識
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#53Non-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
- https://www.ir.com/guides/what-is-network-latency
- https://developers.google.com/web/tools/chrome-devtools/network/understanding-resource-timing
- https://wondernetwork.com/pings
- https://www.pcwdld.com/what-is-mtr-and-howto-troubleshoot-connections
- https://www.linode.com/docs/networking/diagnostics/diagnosing-network-issues-with-mtr/
- https://kinsta.com/blog/reduce-dns-lookups/
- https://stackoverflow.com/questions/36672261/how-to-reduce-ssl-time-of-website
- https://zoompf.com/blog/2014/12/optimizing-tls-handshake/
- https://stackoverflow.com/questions/18215389/how-do-i-measure-request-and-response-times-at-once-using-curl