iT邦幫忙

2026 iThome 鐵人賽

DAY 2
0
IT Operation

低延遲網路的維運工程:從 HFT 現場長出來的 30 天系列 第 2

Day 2:為什麼 ping 量不出低延遲

  • 分享至 

  • xImage
  •  

昨天說今天要從 ping 開始,看它到底差多少。
動手之前我猜大概十倍。量完是幾百倍。而且量完才發現,這個工具回答的根本是另一個問題。

環境

  1. 一台 RHEL 9.8 主機(rhel-node1,26 核,HT 關閉),板載網卡接到 Arista 7150。

  2. ping 打兩個目標:主機自己的 loopback(127.0.0.1),還有交換器的管理 IP(192.0.2.237)。另外寫了 19 行 python 在 loopback 上灌 TCP 測吞吐,拿來當負載用。

動手做

五條指令,每條 10 到 30 秒。

ping -c 2000 -i 0.005 -D 127.0.0.1 > ~/day02/loopback.txt
ping -c 2000 -i 0.005 -D 192.0.2.237 > ~/day02/switch.txt
python3 ~/day02/tput.py 10 | tee ~/day02/tput.txt
taskset -c 3 python3 ~/day02/tput.py 30 > ~/day02/tput_pin.txt 2>&1 & sleep 1 
taskset -c 3 ping -c 2000 -i 0.005 -D 127.0.0.1 > ~/day02/pinned.txt; wait
  • -c 2000 送滿 2000 個封包後自動停止(count)
  • -i 0.005 每個封包間隔 5 毫秒
  • -D 會在每行前面印時戳

然後把 time= 那欄抽出來算百分位數。
https://ithelp.ithome.com.tw/upload/images/20260914/201840635DzgbMHENh.png

數字怎麼讀

rtt 那行的 avg 印出來是 0.000 ms ping 的輸出只到小數第三位,也就是 1 微秒。7150 這種 cut-through 交換器,官方標稱是 350 奈秒。那是標稱值不是我量的,整段轉發時間塞得進ping的一個顯示格子裡。差幾倍我今天不算,因為手上還沒有實測值,後面量出來再回頭補。

ping 交換器量到 163 微秒。 這個數字不是轉發延遲。管理 IP 上的 ICMP 由交換器的 CPU 來回,封包根本沒進轉發晶片,所以量到的是那顆管理 CPU 今天有多忙。min 104 到 max 367,光抖動範圍就有 263 微秒。

64 bytes 跟 1518 bytes 那兩列,六欄裡五欄一模一樣,只有 max 差 1 微秒,而 1 微秒剛好就是 ping 的顯示下限。封包大了 1454 bytes,ping 的輸出幾乎一動也不動。同樣這段資料推上 10G 的線要花 1163 奈秒 (下面計算方法),那個量級 ping 就是看不到。

(1518 - 64) x 0.8 ns/byte = 1163.2 ns

吞吐那邊也一樣。tput.py 在 loopback 上跑出 85.75 Gbit/s,而這條路徑上完全沒有網路。數字很漂亮,但它對延遲一句話都沒說。

https://ithelp.ithome.com.tw/upload/images/20260914/20184063AbIjr48vIj.png

卡住的地方

我原本預測當主機一加壓,ping 的 p99 就會炸開。理由很直覺,吞吐測試吃滿 CPU,ping 要排隊,延遲當然變差。然而實測下來完全沒有。underload 那列的 p99 是 0.001,比沒負載的 0.002 還低,而負載確實有跑滿,30 秒傳了 317 GB。
這台有 26 顆核心,我的腳本只有兩個執行緒,吃滿兩顆,剩 24 顆閒著。ping 永遠排得到空核心,兩邊沒搶過同一個東西。

我錯在把「有負載」直接當成「會競爭」,沒先問它們有沒有搶同一個資源。

所以我用 taskset 把負載跟 ping 都釘在第 3 顆核心上重跑。pinned 那列的中位數從 0.001 變 0.002,整條分布往右移一格,而一格就是 ping 能表示的最小一步。負載自己也慢了,同樣綁在那顆核上,沒有 ping 的時候跑 81.91 Gbit/s,有 ping 剩 71.69。

ping 自己遲到了 908 毫秒

  • -i 0.005 要求每 5.000 毫秒送一包,把 -D 的時戳相鄰相減,就能看它有沒有做到。

https://ithelp.ithome.com.tw/upload/images/20260914/20184063r3DGd5yyvI.png

loopback        (沒綁核、沒負載)
underload       (沒綁核、有負載)
pinned_noload   (綁了核、沒負載)
pinned          (綁了核、有負載)

前三列都貼著 5.000,只有最後一列跳掉,所以那個落後是搶核心造成的,跟 taskset 本身無關。每包多花 0.454 毫秒,2000 包累積下來,ping 自己遲到了 908 毫秒。而它在 rtt 那欄只多了1微秒。

同一次加壓、同一個行程。ping 的輸出多了 1 微秒,實際每包被延誤 454 微秒,差 454 倍。

那 454 微秒不在 ping 的任何一欄輸出裡。RTT 是從封包真的送出去那一刻才起算的,行程被排程器晾在旁邊的那段,發生在碼錶按下之前。
還有一組數字指向同一件事。我寫了個 UDP echo,一樣打 127.0.0.1,一樣一來一回,封包大小也一樣,唯一的差別是回覆由誰產生。

ping       p50 1 µs      max 6 µs
UDP echo   p50 5.52 µs   max 30.26 µs

https://ithelp.ithome.com.tw/upload/images/20260914/20184063LN70NfGOSM.png

ICMP 的回覆是 kernel 在軟中斷裡直接生出來的,不用叫醒任何使用者空間的行程,UDP echo 的回覆要叫醒一個。UDP echo 平常那一下就已經接近 ping 在同一條路徑上量到的最壞值,max 更是差了五倍。

這件事在維運上要幹嘛

先講一個跟上面完全同源的狀況。之前同事說印表機沒反應,我 ping 那台印表機的IP可以通,但就是連不上。後來重開機幾次就好了,那時候我也不知道具體原因是什麼,只覺得 ping 不太準。
做完今天這組才想通,ping 通不代表那台機器能用,它只證明那台機器的 kernel 還活著。服務行程卡死,網路堆疊照樣回 ICMP。實驗室裡 UDP echo 那五倍是溫和版本,現場的極端版本就是服務已經掛了,而 ping 持續回應。所以有兩件事現在可以確定:

ping 通不等於服務可用。

監控只有 ICMP,等於只監控到 kernel 活著。要知道服務能不能用,探測至少要打一次它真正的服務埠。

看百分位數,不要看平均。

今天 avg 那欄印出來是 0.000,等於什麼都沒說,p99 跟 max 至少還告訴我分布右邊長什麼樣子。
至於門檻要訂多少我還沒有答案,得先有一組基準數字才談得上。

明天開始碰硬體時戳,先弄清楚 ExaNIC 的時戳是誰打的、打在封包的哪個位置。


上一篇
Day 1:低延遲網路調完之後,你怎麼知道它今天還是快的
下一篇
Day 3:硬體時戳是什麼,ExaNIC 的時戳從哪來
系列文
低延遲網路的維運工程:從 HFT 現場長出來的 30 天10
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言