JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

診斷「網路好慢」

「網路好慢」是計算機世界裡最含糊的抱怨——也是最常見的。本篇收尾,把這一級的工具與詞彙,化成一套冷靜、分層的方法,讓你找出「慢」究竟住在哪裡,而不是用猜的。

為什麼「慢」在你把它拆開之前毫無意義

有人說「網路好慢」。這一個字底下,至少藏著四個截然不同的問題,而一個細心的診斷者,第一件事就是「在這個字被拆開之前,拒絕接受它」。那個半天才開始載入的網頁,是延遲問題。那個爬行般的大型下載,是吞吐量問題。那個一頓一頓、畫面撕裂的視訊通話,是抖動丟包問題。那個撐了一分鐘就斷掉的連線,又是另一回事。正如這一級前幾篇一再強調的,延遲、吞吐量、goodput 是三件不同的事——所以「慢」不是一個量測值,它是一種感覺,而你的任務,是把感覺變成數字。

下面這個誤解,浪費掉的時間比任何其他誤解都多:人們以為「慢」就等於「頻寬不夠」,然後急著去買一條更快的線。但頻寬、吞吐量、延遲是彼此獨立的。從 100 Mbps 升級到 1 Gbps,對一個「因為每次點擊都在等一個慢吞吞的 DNS 查詢、或一台遠在天邊的伺服器」而感覺遲鈍的網頁,毫無幫助——你贏不了光速,一條更粗的管子,並不會縮短光必須走的距離。更多頻寬讓桶填得更快;它不會讓第一滴水更早抵達。光是搞清楚你缺的是這兩樣的哪一樣,診斷就已經完成一半。

從底層往上爬

把任何網路問題定位的可靠辦法,是「按順序測試各層,從最低層開始,並在第一個失敗的地方停下」——因為低層的失敗,會讓它上面的一切看起來也壞了。如果機器連自己的路由器都搆不到,那除錯一個慢吞吞的網頁就毫無意義。所以你沿著這座階梯一開始就學過的那疊巢狀信封往上走,一次爬一層,每一層只問一個是非題:這層通不通,又有多快?

  1. 第一、二層,本地鏈路:網路線插好了嗎、Wi-Fi 關聯上了嗎,訊號好嗎?一個微弱的 Wi-Fi 訊號,會默默地重傳訊框,在你怪罪到網際網路頭上之前,就先把它上面的一切搞癱。
  2. 第三層,你自己的網路:你搆得到你的預設閘道(你的路由器)嗎?對路由器位址快速 ping 一下,就能證明本地這一跳是通的、來回時間很小。如果這一步就失敗,問題出在你自家或辦公室,不在網際網路。
  3. 第三層,更廣的網際網路:ping 一個眾所周知、可靠的位址。如果你的路由器有回應、但更廣的網際網路沒有,麻煩就出在你的 ISP 或它的上行鏈路,而不是你的設備。
  4. 命名:你能把主機名稱解析成位址嗎?單獨為一次 DNS 查詢計時。一個「在任何資料流動之前就卡住」的網頁,極常是名稱解析慢或失敗,而根本不是網路慢。
  5. 第四到七層,服務本身:現在,也唯有現在,才去測試真正的應用——抓取那個 URL,量測「首位元組時間」與總時間。如果底下一切都健康,那「慢」就住在這裡——在伺服器,或在你與它之間的傳輸層。

注意這套邏輯:每一步都在下一步開始之前,排除掉一整片可能性的區域。等你爬到應用層時,你已經排除了你的網路線、你的 Wi-Fi、你的路由器、你的 ISP、你的 DNS——所以如果網頁還是慢,你已經把兇手逼進了一個很小的空間。這就是「除錯」與「瞎忙」的分別:瞎忙的人重新整理頁面然後禱告;診斷者則不斷對問題二分,直到只剩一種解釋能活下來。

是延遲還是吞吐量?分辨它們的兩件工具

一旦你懷疑路徑本身,有兩個量測能把兩種「慢」分開。要檢查延遲與丟包,用 ping:它送出一個小探針、為來回計時,正如這一級第二篇所示,它回報來回時間(RTT)、以及「從來沒回來」的探針所佔的比例,那就是丟包。Ping 回答的是「一個小小的東西去那裡再回來,要花多久、又是否可靠地抵達?」一個穩定、低的 RTT 配上零丟包,意味著這條路徑對互動式工作而言本質上沒問題——不管大檔案感覺起來如何。

要檢查吞吐量,用 iperf:它在兩台你能掌控的機器之間,跑一場持續的傳輸,量測每秒實際流過多少位元。這是「我在這條路徑上,到底能多快搬動大宗資料?」的誠實答案——而它常常遠低於你方案上印的頻寬,因為吞吐量是由瓶頸鏈路決定的,也就是整條路徑上最慢的那一跳,正如上一篇用 min(R1, R2, ...) 解釋的那樣。一條路徑可以有完美的 ping、卻有糟糕的 iperf 吞吐量;也可以有不錯的吞吐量、卻有惱人的 ping;這兩件工具量的是真正不同的東西,而你通常兩個都需要。

痛點在路徑上的哪裡?

Ping 與 iperf 告訴你路徑是否慢;traceroute 則開始告訴你慢在哪裡。回想它在第二篇那個漂亮的把戲:它沒有任何特權能看進網路內部——它只是「濫用」存活時間(TTL)欄位,送出一些被刻意設定成「在第 1 跳、第 2 跳、第 3 跳過期」的封包,再蒐集每台路由器在封包死在它門口時送回來的那則錯誤訊息。那串路由器、配上到每一台的來回時間,就是這條路徑、以及延遲在哪裡累積起來的一張粗略地圖。盯著「RTT 突然跳高、而且其後每一跳都維持高」的那一跳——那一步,就是你的頭號嫌犯。

但 traceroute 要求誠實地解讀,而這正是初學者誤診之處。某一跳顯示出高 RTT,未必就是問題:許多路由器把「回答這些垂死探針」這件工作的優先權壓低,所以一跳可能看起來慢、而每個只是「路過」它的封包卻好端端的。真正重要的訊號,是「一個延遲跳升、之後所有跳都維持」,因為那反映了「真的沿著路徑被帶下去」的延遲。在某一跳暴衝、卻在下一跳消失的尖刺,幾乎總是那台路由器懶得回覆,而不是真正的瓶頸。讀「跨多跳的趨勢」,永遠別孤立地讀單獨一跳。

Traceroute 也有些真實的盲點值得點名。去程與回程的路徑可能不同,所以它顯示的 RTT 混了兩個方向、可能誤導你。有些路由器與防火牆乾脆把探針丟掉,留下一排星號,那意思是「沒有回覆」,而不是「路徑斷了」。而 CDN 與負載平衡的把戲,意味著路由可能在兩次執行之間就變了。Traceroute 是個速寫畫家,不是測量員:它給你一條「該調查哪一段」的有力線索,而不是一份法庭等級的證據。把它的輸出當成一個「待確認的假設」,而不是一個判決。

當顯而易見的工具用完時:去看封包

有時候 ping 沒事、iperf 沒事、traceroute 乾乾淨淨——而某個特定的應用還是慢。這時你停止「探測」,開始「觀看」,靠的是封包擷取。正如第三篇所示,tcpdump 與 Wireshark 讓你錄下真正的封包、讀出這場對話實際做了什麼。用一個 BPF 過濾器,只留下你在乎的流量——擷取一切會把你淹死,所以一條像「那台慢伺服器的主機,加上 TCP port 443」這樣的過濾器,能在你還沒打開檔案之前,就把錄影修剪成「就那一場對話」。

封包能講出摘要工具講不出的故事。大量的重傳與重複確認,意味著路徑正在丟封包,而傳統的 TCP 把那個丟包讀成壅塞、於是自我節流——這在有線鏈路上恰恰是對的一步,但在一條不穩的 Wi-Fi 鏈路上卻是誤判,因為那個丟包只是無線電干擾,而不是佇列塞滿。請求與回覆之間一段又長又平的停頓,指向「伺服器在想事情」,而非網路。一條連線以乾淨的三向交握開場、卻接著以一小塊一小塊、走走停停的方式傳輸,可能撞上了流量控制或一個過小的視窗。追蹤檔裡每一種樣態,都指向一個不同的兇手,而唯有封包能讓你看出是哪一個。

Symptom in the capture                      Most likely cause
--------------------------------------------------------------------------
many retransmissions + dup ACKs          -> packet loss (congestion, or Wi-Fi)
long gap AFTER request, before reply     -> slow server, not the network
transfers in tiny stop-start bursts      -> small window / flow control / BDP
slow or failed name lookup before SYN    -> DNS, not the data path
clean handshake, then connection resets  -> firewall or server dropping it
一份入門對照表:在封包擷取裡可以辨認出的常見樣態,以及每一種各自指向的診斷。封包把含糊的「它很慢」,變成一個明確、可被檢驗的假設。

從救火,到時時看著網路

到此為止的一切都是被動的:一個人在抱怨出現之後,才去跑一件工具。這對一台筆電行得通,但它無法擴展到一個數以千計裝置的網路——在那裡,有趣的故障都是間歇性的,等任何人登入時早已消失。成熟的做法,是讓網路持續地看著自己,好讓「事情出錯時你需要的資料」早已被記錄下來。這就是從「除錯」走向可觀測性的轉變——打造一個「你能從外部理解其內部狀態、而不必在那個倒楣的時刻剛好站在現場」的網路。

那些零件,就是這一級其餘的詞彙。SNMP 與更老的計數器,讓裝置回報基本的健康狀況——介面是通是斷、進與出的位元組數。像 NetFlow 與 sFlow 這樣的流量紀錄,摘要出「誰跟誰講話、講了多少」,讓你不必儲存每一個封包就能看見流量樣態。而現代的遙測,則讓裝置持續地把豐富、細緻的資料串流給一個收集器,而不是等著被輪詢。把這一切餵進儀表板與警報,「網路好慢」就不再是一場慌亂追獵的起點,而變成一個「瞄一眼那張早已自己畫好的圖」就能回答的問題。

這就是這一級完整的弧線。你學會了主動量測與被動量測的分別;ping 與 traceroute 真正告訴你什麼、又在哪裡說謊;如何用擷取讀真正的封包;以及那套把延遲、吞吐量、goodput 三者分開的精確詞彙,配上瓶頸與頻寬延遲乘積,解釋為什麼一條快線依然可能感覺很慢。這收尾的一篇,只是把它們組裝成一個習慣:拒絕「慢」這個字,把它拆成數字,爬過各層,定位痛點,去看封包,並最終讓網路自己量測自己,好讓答案在問題被問出之前,就已經在那裡等著。