絡(luò)路徑探測與可視化實(shí)戰(zhàn))
RouteScope 這個(gè)名字最初只是我電腦里一個(gè)不起眼的工具腳本名意思是“把路由路徑放進(jìn)觀測視野里”。后來它慢慢變成了我處理網(wǎng)絡(luò)故障時(shí)最先打開的東西一條命令把從本機(jī)到目標(biāo) IP 之間每一跳的設(shè)備、延遲、丟包和 AS 歸屬全部拉出來再按時(shí)間軸回放對(duì)比。這篇文章就圍繞 RouteScope 這個(gè)項(xiàng)目聊聊我為什么做它、路徑探測的原理是什么、怎么用 Python 搭一個(gè)能用的原型以及落地過程中踩過的那些坑。如果你想排查“ping 通但業(yè)務(wù)卡”“延遲忽高忽低”“路徑莫名繞路”這類問題或者想給自己的監(jiān)控體系補(bǔ)上“路徑可視化”這塊拼圖這篇內(nèi)容應(yīng)該能幫你省不少時(shí)間。1. 做 RouteScope 之前先想清楚它要解決什么問題1.1 ping 通不等于鏈路健康很多朋友排查網(wǎng)絡(luò)問題有個(gè)習(xí)慣先 ping。ping 通就覺得鏈路沒問題然后開始查服務(wù)器負(fù)載、查數(shù)據(jù)庫慢查詢、查應(yīng)用日志折騰半天沒結(jié)論最后才發(fā)現(xiàn)問題出在中間鏈路上。我遇到過最典型的一個(gè)案例某地到云上業(yè)務(wù)的 TCP 連接頻繁超時(shí)業(yè)務(wù)方堅(jiān)持說網(wǎng)絡(luò)沒問題因?yàn)樗麄冊搭^ ping 目標(biāo)機(jī)房的 IP 一直是通的延遲在 10ms 以內(nèi)。但實(shí)際抓包發(fā)現(xiàn) TCP 握手的 SYN 包發(fā)出去之后ACK 回得非常慢而且丟包集中在特定時(shí)段。這種情況 ping 根本看不出來因?yàn)?ping 用的是 ICMP走的轉(zhuǎn)發(fā)優(yōu)先級(jí)和實(shí)際業(yè)務(wù)流量不一定一樣而且 ping 只告訴你“目標(biāo)通不通”根本不告訴你“路徑上到底哪一段出了問題”。1.2 RouteScope 的核心定位把 trace 從“命令”變成“視圖”傳統(tǒng)的 traceroute 能列出每一跳 IP但輸出是純文本信息太碎。你要自己盯著一堆 IP 判斷哪一跳異常還要手動(dòng)跑好幾次才能確認(rèn)路徑是否漂移。如果目標(biāo)路徑跨多個(gè)運(yùn)營商、多個(gè)地域一次 trace 的輸出根本不足以支撐判斷。RouteScope 的定位就是把這些原始輸出變成結(jié)構(gòu)化的、可對(duì)比的、可告警的視圖。它做三件事把每一跳的 IP、RTT、丟包率、AS 歸屬整理成統(tǒng)一的結(jié)構(gòu)化數(shù)據(jù)多次探測結(jié)果按時(shí)間存儲(chǔ)能回放“路徑是否變了”“延遲是否在惡化”當(dāng)路徑變化、丟包率超過閾值時(shí)產(chǎn)生告警而不是等你肉眼去發(fā)現(xiàn)。簡單說它解決的是“從 A 到 B 的網(wǎng)絡(luò)路徑到底走得好不好”這個(gè)問題的可觀測性。1.3 現(xiàn)有工具和我想要的差異市面上不是沒有類似能力比如 mtr、Grafana 的 Blackbox Exporter、各種商業(yè)網(wǎng)絡(luò)監(jiān)控產(chǎn)品。但我實(shí)際用下來都差點(diǎn)意思列個(gè)對(duì)比表更直觀工具/方案能看路徑能歷史回放能路徑變化告警部署成本我的痛點(diǎn)traceroute是否否極低純文本難對(duì)比mtr是否實(shí)時(shí)持續(xù)否極低數(shù)據(jù)沒落地?zé)o法回看Blackbox Exporter部分是配合 Prometheus是中默認(rèn)按探針拿 RTT路徑細(xì)節(jié)不足商業(yè)監(jiān)控產(chǎn)品是是是高貴且閉環(huán)難定制RouteScope 走的是“輕量、自助、能落庫”的路線核心探測邏輯很簡單存儲(chǔ)用 SQLite 或 InfluxDB 都行告警直接對(duì)接現(xiàn)有的 Alertmanager 或者釘釘/郵件。它不追求替代商業(yè)產(chǎn)品而是補(bǔ)上“我自己可掌控的路徑觀測能力”這塊短板。1.4 為什么這個(gè)名字要帶 Scope名字里帶 Scope 有兩個(gè)原因。一是本意我要把路徑的“范圍”看清楚二是在 IPv6 的世界里 scope 本身就是一個(gè)技術(shù)術(shù)語鏈路本地地址fe80::/10是有 scope 的處理多網(wǎng)卡主機(jī)時(shí)要區(qū)分報(bào)文從哪個(gè)接口進(jìn)來。這個(gè)細(xì)節(jié)后文會(huì)專門講算是一個(gè)隱藏雙關(guān)。2. 路徑探測的原理讀懂每一跳的應(yīng)答2.1 TTL 耗盡機(jī)制路徑探測最底層的原理還是 TTLTime To Live。IP 報(bào)文每經(jīng)過一個(gè)路由器TTL 減 1減到 0 時(shí)路由器丟棄報(bào)文同時(shí)給源地址回一個(gè) ICMP Time Exceeded 報(bào)文。我們只要從 TTL1 開始逐跳發(fā)包就能讓路徑上每一臺(tái)路由器都“被迫”向我們報(bào)一次到。這里有個(gè)生活化的類比TTL 就像游戲里的體力值每過一個(gè)關(guān)卡扣一格血血扣完了關(guān)卡守衛(wèi)會(huì)喊一句“你出局了”并且告訴你“我是誰”。我們從第一關(guān)開始每一關(guān)都派人去送死就能把整條路線上的守衛(wèi)全部問出來。要注意這個(gè)機(jī)制依賴中間設(shè)備“配合”回 ICMP。如果設(shè)備禁用了 ICMP Time Exceeded 的發(fā)送那這一跳就會(huì)顯示為*但不代表設(shè)備不存在。后面我會(huì)講怎么區(qū)分“設(shè)備不回”和“設(shè)備真的掛了”。2.2 ICMP、UDP、TCP 三種探測方式實(shí)際寫探測邏輯時(shí)不可能只發(fā) ICMP Echo Request那樣目標(biāo)往往直接回 Echo Reply中間跳的 TTL 超時(shí)信息也能拿到但很多網(wǎng)絡(luò)設(shè)備對(duì) ICMP 的限速最狠丟包率看起來很高容易誤判。所以一般有三種探測方式方式發(fā)送的包期待的回包優(yōu)點(diǎn)缺點(diǎn)ICMP EchoICMP Echo RequestTime Exceeded / Echo Reply目標(biāo)容易識(shí)別中間設(shè)備限速嚴(yán)重容易誤報(bào)丟包UDPUDP 到高位端口Time Exceeded / Port Unreachable傳統(tǒng) traceroute 方式較“友好”某些防火墻直接靜默丟棄 UDPTCP SYNTCP SYN 到指定端口Time Exceeded / SYN-ACK能探測特定服務(wù)的可達(dá)性需要 root 權(quán)限構(gòu)造 TCP 包我實(shí)際用得最多的是 UDP因?yàn)樗罱咏鼈鹘y(tǒng) traceroute 的行為而且不容易被中間設(shè)備針對(duì)。但如果目標(biāo)主機(jī)的防火墻把高位 UDP 端口全封了最后一跳會(huì)一直顯示*這時(shí)就得切到 TCP SYN 去確認(rèn)目標(biāo)本身是否可達(dá)。2.3 路徑漂移與多路徑還有一個(gè)容易忽略的問題同一時(shí)刻、同一對(duì)源和目標(biāo)路徑不一定是唯一的。很多骨干網(wǎng)會(huì)用 ECMP等價(jià)多路徑做負(fù)載均衡同一個(gè) TTL 的多個(gè)探測包可能走到不同的下一跳。如果只發(fā)一個(gè)包你看到的只是“某一條路徑”下次再發(fā)可能就是另一條。這會(huì)導(dǎo)致一個(gè)非常誤導(dǎo)人的現(xiàn)象兩次 trace 的結(jié)果不一樣中間多了或少了一跳看起來像“路由繞路了”其實(shí)只是負(fù)載均衡把流量分?jǐn)偟搅瞬煌溌飞?。RouteScope 的應(yīng)對(duì)策略是同一個(gè) TTL 連續(xù)發(fā)多個(gè)探測包統(tǒng)計(jì)這一跳返回的所有不同源 IP。如果多個(gè)結(jié)果不一致就把這個(gè) TTL 標(biāo)記為“多路徑節(jié)點(diǎn)”而不是簡單地覆蓋上一次的結(jié)果。這個(gè)設(shè)計(jì)非常重要也是我早期踩坑踩得最狠的地方。2.4 AS 歸屬與地理位置把每一跳的 IP 打上 AS 編號(hào)是 RouteScope 比普通 traceroute 好用很多的地方。AS 全稱 Autonomous System自治系統(tǒng)你可以把它理解成一個(gè)“網(wǎng)絡(luò)機(jī)構(gòu)的世界語編號(hào)”??吹铰窂綇腁S13335跳到AS4134你能立刻知道流量從一個(gè)運(yùn)營商網(wǎng)絡(luò)切到了另一個(gè)或另一個(gè)機(jī)構(gòu)網(wǎng)絡(luò)路徑是否在跨網(wǎng)繞路一目了然。地理位置信息反而要看場景。IP 地理定位庫的準(zhǔn)確度參差不齊我一般只把 AS 和幾個(gè)粗粒度標(biāo)簽比如“骨干網(wǎng)內(nèi)”“國際出口”“云廠商接入點(diǎn)”作為參考不拿它當(dāng)精確判斷依據(jù)。3. 用 Python Scapy 寫一個(gè)最小可用的 RouteScope 原型3.1 為什么先選 Python 和 Scapy做原型階段我選了 Python Scapy原因很實(shí)際Scapy 構(gòu)造和解析網(wǎng)絡(luò)包非常方便不用手動(dòng)拼 IP 頭和 ICMP 頭十幾行代碼就能實(shí)現(xiàn)一次探測適合快速驗(yàn)證思路。等邏輯穩(wěn)定了我再考慮用 Go 重寫一遍核心探測器因?yàn)?Scapy 在并發(fā)大流量下的解析性能和 GIL 限制確實(shí)是瓶頸但那是后話。先安裝依賴pip install scapy然后在 Linux 機(jī)器上跑因?yàn)槲倚枰?root 權(quán)限來構(gòu)造原始套接字。Windows 上也能跑但需要裝 Npcap而且某些防火墻行為會(huì)導(dǎo)致結(jié)果不如 Linux 直觀。macOS 需要給 Python 進(jìn)程額外授權(quán)稍微麻煩一點(diǎn)。3.2 單條路徑探測代碼實(shí)現(xiàn)我直接貼一個(gè)最簡版只做一件事從 TTL1 到 TTL30每個(gè) TTL 發(fā) 3 個(gè) UDP 探測包把每一跳的 IP 和 RTT 收集起來。#!/usr/bin/env python3 import time from scapy.all import IP, ICMP, UDP, sr1 TARGET 1.1.1.1 MAX_TTL 30 PROBES 3 TIMEOUT 2.0 def single_probe(target, ttl, probe_id): # 傳統(tǒng) traceroute 會(huì)從 33434 開始遞增目標(biāo)端口避免探測包之間相互復(fù)用 dport 33434 probe_id pkt IP(dsttarget, ttlttl) / UDP(dportdport) start time.time() reply sr1(pkt, timeoutTIMEOUT, verboseFalse) rtt (time.time() - start) * 1000 if reply is None: return {ip: None, rtt: None, type: timeout} if reply.haslayer(ICMP): # ICMP type 11 是 Time Exceededtype 3 是 Port Unreachable return {ip: reply.src, rtt: rtt, type: reply[ICMP].type} return {ip: reply.src, rtt: rtt, type: reply} def trace(target): for ttl in range(1, MAX_TTL 1): hops [] for probe_id in range(PROBES): result single_probe(target, ttl, probe_id) hops.append(result) ips list({h[ip] for h in hops if h[ip] is not None}) status multi if len(ips) 1 else single print(fTTL {ttl:2d} | {status:6s} | {[h[ip] for h in hops]} | RTT {[round(h[rtt], 1) if h[rtt] else None for h in hops]}) if reply in [h[type] for h in hops]: print(Reached target, stopping.) break if __name__ __main__: trace(TARGET)這段代碼有幾個(gè)關(guān)鍵點(diǎn)值得展開目標(biāo)端口為什么要遞增如果每次都發(fā)同一個(gè) UDP 端口某些目標(biāo)主機(jī)會(huì)對(duì)同一個(gè)目的端口的行為進(jìn)行緩存后續(xù)包可能被直接丟棄或做特殊處理按 probe_id 遞增可以在一定程度上規(guī)避。sr1的 timeout 設(shè) 2 秒合理嗎對(duì)國內(nèi)跨網(wǎng)路徑2 秒基本夠用如果路徑非常擁堵或目標(biāo)很遠(yuǎn)可以提高到 3 秒。但 timeout 越久整個(gè) trace 時(shí)間越長30 跳 × 3 次 × 2 秒最壞情況要 3 分鐘。實(shí)際工程里我會(huì)用并發(fā)發(fā)送的方式壓縮時(shí)間。判斷“到達(dá)目標(biāo)”不能只看 ICMP Port Unreachable因?yàn)榭赡苣繕?biāo)根本不開對(duì)應(yīng) UDP 端口要結(jié)合 type 3 和 type 11 一起看必要時(shí)用 TCP SYN 確認(rèn)。3.3 多路徑發(fā)現(xiàn)與數(shù)據(jù)聚合單跳探測只是基礎(chǔ)真正有價(jià)值的是把多次探測結(jié)果匯總。我在原型里加了一個(gè)聚合層對(duì)同一個(gè) TTL把多包返回的 IP 集合、RTT 最小值/平均值/最大值、丟包數(shù)都記錄下來。def aggregate_hops(results): aggregate [] for ttl_block in results: rtts [h[rtt] for h in ttl_block if h[rtt] is not None] ips list({h[ip] for h in ttl_block if h[ip] is not None}) loss sum(1 for h in ttl_block if h[ip] is None) aggregate.append({ ttl: ttl_block[0][ttl], ips: ips, rtt_min: min(rtts) if rtts else None, rtt_avg: sum(rtts) / len(rtts) if rtts else None, rtt_max: max(rtts) if rtts else None, loss: loss, multi: len(ips) 1 }) return aggregate這里要注意loss 不能簡單等于“丟包數(shù)除以發(fā)包數(shù)”因?yàn)橹虚g設(shè)備可能只是限速 ICMP而不是真的丟業(yè)務(wù)包。所以我在界面上會(huì)把“探測包丟包率”和“業(yè)務(wù)實(shí)際丟包”分開展示避免誤導(dǎo)。3.4 結(jié)果輸出與簡單可視化聚合后的數(shù)據(jù)我習(xí)慣轉(zhuǎn)成 JSON 落盤這樣后面不管接 Grafana 還是自己畫頁面都方便。{ target: 1.1.1.1, time: 2025-01-15T10:30:00Z, path: [ {ttl: 1, ips: [192.168.1.1], rtt_avg: 1.2, loss: 0}, {ttl: 2, ips: [203.0.113.1], rtt_avg: 8.9, loss: 0} ] }可視化我用的是 ECharts 的關(guān)系圖把每一跳當(dāng)成一個(gè)節(jié)點(diǎn)相鄰 TTL 的節(jié)點(diǎn)之間連一條線。如果某個(gè) TTL 存在多個(gè) IP就畫出多分支一眼就能看出路徑是否在負(fù)載均衡。節(jié)點(diǎn)大小按平均 RTT 映射顏色按丟包率漸變這樣“哪一跳在抖”非常直觀。4. 從原型到可落地工具的四個(gè)細(xì)節(jié)4.1 探測頻率與并發(fā)控制原型跑起來之后不能直接每秒鐘跑一次。對(duì)公網(wǎng)目標(biāo)高頻發(fā)包輕則被目標(biāo)安全策略封禁重則影響正常業(yè)務(wù)這一點(diǎn)必須克制。我的建議是默認(rèn)每 60 秒一輪完整路徑探測一條路徑一輪最多 30 跳 × 5 個(gè)探測包每包間隔 200ms 以上如果要縮短一輪時(shí)間用并發(fā)發(fā)送而非縮短間隔。并發(fā)發(fā)送可以用 Scapy 的sr()一次發(fā)多個(gè)包但要注意回調(diào)解析。實(shí)際跑下來30 跳并發(fā)一輪大約 5 到 8 秒能完成相比串行的 2 到 3 分鐘快太多了。不過并發(fā)時(shí)系統(tǒng)會(huì)瞬時(shí)產(chǎn)生一批原始套接字報(bào)文對(duì)本地網(wǎng)卡和 CPU 有一點(diǎn)壓力單機(jī)同時(shí)跑幾十個(gè)路徑?jīng)]問題不要貪多。4.2 IPv6、鏈路本地地址和 Scope 處理做 IPv6 探測時(shí)最容易被忽略的就是鏈路本地地址。如果用fe80::開頭的地址作為探測源或目標(biāo)Linux 內(nèi)核要求你同時(shí)指定scope也就是出接口比如fe80::1%eth0。Scapy 里構(gòu)造 IPv6 包時(shí)如果目標(biāo)字段帶%后綴需要先把接口名解析出來。from scapy.all import IPv6, UDP, sr1 import socket def build_ipv6_target(addr_with_scope): if % in addr_with_scope: addr, iface addr_with_scope.split(%) # 構(gòu)造報(bào)文時(shí)通過 iface 參數(shù)指定出接口 return addr, iface return addr_with_scope, None這個(gè)細(xì)節(jié)和 RouteScope 的名字意外契合scope 在 IPv6 世界里就是一個(gè)真實(shí)存在的概念。如果處理多網(wǎng)卡主機(jī)不處理 scope探測包可能從錯(cuò)誤的接口發(fā)出去導(dǎo)致路徑完全不對(duì)。我在一臺(tái)雙網(wǎng)卡服務(wù)器上踩過這個(gè)坑排查了半天才發(fā)現(xiàn)是源地址選擇問題。4.3 數(shù)據(jù)存儲(chǔ)與趨勢告警原型階段數(shù)據(jù)存在 SQLite 就夠表結(jié)構(gòu)很簡單核心字段就是target、timestamp、ttl、ips、rtt_min、rtt_avg、rtt_max、loss。如果要長期存儲(chǔ)多個(gè)監(jiān)測點(diǎn)再遷移到 InfluxDB我自己的經(jīng)驗(yàn)是按target timestamp ttl作為 tag 和 field 的組合查詢性能最好。告警邏輯我拆成兩個(gè)規(guī)則路徑變化告警當(dāng)任意一跳的 IP 集合與上一個(gè)時(shí)間窗口完全不同且不是由于多路徑正常輪換時(shí)說明路徑發(fā)生了切換質(zhì)量劣化告警連續(xù) 3 輪探測中同一跳丟包率超過 10% 或平均 RTT 超過歷史基線的 1.5 倍。第一個(gè)規(guī)則特別有用。很多時(shí)候業(yè)務(wù)卡頓不是因?yàn)閹挷粔蚨锹窂奖磺械搅艘粭l繞遠(yuǎn)的鏈路上RTT 從 20ms 變成 80ms。路徑變化告警能第一時(shí)間告訴你“網(wǎng)絡(luò)路由可能變了”這時(shí)候再去看 BGP 或運(yùn)營商側(cè)的信息方向就對(duì)了。4.4 安全邊界只讀探測也有合規(guī)紅線這點(diǎn)必須單獨(dú)說。路徑探測是只讀操作但它不是無副作用的過多的探測流量會(huì)對(duì)中間設(shè)備和目標(biāo)產(chǎn)生負(fù)載。我不建議對(duì)非授權(quán)目標(biāo)做高頻長時(shí)間探測尤其不要用 RouteScope 去“巡檢”別人的公網(wǎng)服務(wù)器。如果要在公司內(nèi)部部署先確認(rèn)探測目標(biāo)屬于自己或合作方在合理范圍內(nèi)使用。另外構(gòu)造原始 IP 包需要較高的系統(tǒng)權(quán)限這本身就是一把雙刃劍。工具本身是網(wǎng)絡(luò)診斷用途但一定要控制部署面別讓腳本落到不相關(guān)的人手里。我自己的原則是生產(chǎn)環(huán)境的探測 Agent 只跑在公司監(jiān)控網(wǎng)段目標(biāo)列表白名單化不做任意 IP 探測。5. 實(shí)操過程里踩過的坑和排查速查表5.1 常見異?,F(xiàn)象速查表工具做到后面真正值錢的是“遇到問題知道怎么排查”。我把踩過的坑整理成了一張表每次新環(huán)境出問題先對(duì)著它查現(xiàn)象可能原因處理辦法從某跳開始全是*中間設(shè)備限速 ICMP或不回 Time Exceeded增大 timeout換成 TCP SYN 探測對(duì)比多輪結(jié)果兩次 trace 路徑差一跳ECMP 負(fù)載均衡導(dǎo)致路徑漂移增加同 TTL 探測包數(shù)量標(biāo)記為 multi不要當(dāng)故障目標(biāo)可達(dá)但 traceroute 不完結(jié)目標(biāo)防火墻丟棄 UDP 高位端口用 TCP SYN 到 80/443 端口確認(rèn)腳本報(bào) PermissionError原始套接字需要 root 權(quán)限sudo運(yùn)行或給進(jìn)程加CAP_NET_RAW探測延遲很高但業(yè)務(wù)正常ICMP 被 QoS 降級(jí)不代表業(yè)務(wù)路徑差用業(yè)務(wù)端口做 TCP SYN 探測交叉驗(yàn)證IPv6 路徑探測不通鏈路本地地址缺 scope 或源地址選擇錯(cuò)誤顯式指定出接口檢查路由表虛擬機(jī)上探測結(jié)果異常虛擬交換機(jī)/安全組過濾 ICMP換物理機(jī)或調(diào)整安全組規(guī)則5.2 一次“第二跳丟包 80%”的排障實(shí)錄舉一個(gè)實(shí)際例子。有段時(shí)間監(jiān)測數(shù)據(jù)顯示從辦公網(wǎng)到某個(gè)云廠商接入點(diǎn)的路徑上第二跳丟包率高達(dá) 80%但是第三跳以后丟包率卻接近 0。第一反應(yīng)是第二跳設(shè)備出了嚴(yán)重問題但是結(jié)合業(yè)務(wù)實(shí)際訪問又似乎沒有明顯故障。后來我同時(shí)跑了三條探測一條 ICMP、一條 UDP、一條 TCP SYN結(jié)果 ICMP 路徑顯示第二跳丟包嚴(yán)重UDP 路徑相對(duì)正常TCP SYN 路徑幾乎不丟。這就說明第二跳設(shè)備大概率只是對(duì) ICMP 限速比較狠而不是轉(zhuǎn)發(fā)有問題。再配合設(shè)備側(cè) SNMP 接口計(jì)數(shù)確認(rèn)物理鏈路沒有 CRC 錯(cuò)誤最終判定這是“假丟包”。這個(gè)案例給我的教訓(xùn)是任何單協(xié)議的單次探測結(jié)果都不能直接當(dāng)結(jié)論。RouteScope 的聯(lián)動(dòng)多協(xié)議探測能力就是我對(duì)比之后專門加進(jìn)去的。現(xiàn)在遇到異常我會(huì)先看“是不是所有探測方式都丟包”如果只有一種協(xié)議丟基本可以判定是設(shè)備策略導(dǎo)致的探測噪音。5.3 探測時(shí)間窗和基線問題另一個(gè)容易忽略的問題是“用什么時(shí)候的數(shù)據(jù)做基線”。很多告警系統(tǒng)第一次接入時(shí)會(huì)立刻建立基線但如果路徑一開始就是劣化的基線本身就不健康后續(xù)永遠(yuǎn)不告警。我在初始化 RouteScope 時(shí)會(huì)先跑 24 小時(shí)“觀察期”把這段時(shí)間的數(shù)據(jù)作為基線之后如果某跳 RTT 超過觀察期的 P95 一定比例才觸發(fā)告警。還有時(shí)間窗口粒度的問題。按 60 秒一輪的頻率單輪數(shù)據(jù)本身噪聲不小我計(jì)算告警用的是 5 分鐘滑動(dòng)窗口窗口內(nèi)有 5 輪數(shù)據(jù)去除最大值和最小值后再取平均這樣能過濾掉瞬時(shí)抖動(dòng)帶來的誤報(bào)。5.4 存儲(chǔ)膨脹控制路徑探測數(shù)據(jù)增長很快如果一分鐘一輪、一輪 30 跳一臺(tái)機(jī)器監(jiān)測 20 條路徑一天就是 86 萬條記錄。雖然 SQLite 也能扛但查詢速度會(huì)變慢。我在實(shí)際使用中做兩級(jí)壓縮原始逐輪數(shù)據(jù)只保留 24 小時(shí)超過 24 小時(shí)后聚合為 5 分鐘一條的摘要超過 30 天后只保留每日的極值、均值路徑指紋。路徑指紋是我自己定義的一個(gè)字符串比如192.168.1.1|203.0.113.1|...|1.1.1.1專門用來快速判斷路徑是否發(fā)生變化。這樣歷史回放時(shí)不用查每一跳明細(xì)直接對(duì)比指紋就能知道哪天路徑改變了。6. 一點(diǎn)后續(xù)可以繼續(xù)擴(kuò)展的空間工具做到現(xiàn)在這個(gè)程度對(duì)我日常工作已經(jīng)夠用了但還有幾個(gè)方向可以繼續(xù)做深。一個(gè)是把多個(gè)監(jiān)測點(diǎn)數(shù)據(jù)放一起做橫向?qū)Ρ缺热鐝牟煌鞘蟹謩e探測同一個(gè)目標(biāo)能更準(zhǔn)確定位“問題出在哪個(gè)區(qū)域、哪段鏈路上”。另一個(gè)是接入 BGP 數(shù)據(jù)當(dāng)路徑變化告警觸發(fā)時(shí)自動(dòng)拉取路由表看看有沒有異常的前綴通告把“網(wǎng)絡(luò)路徑變化”和“路由源頭變化”關(guān)聯(lián)起來。這些進(jìn)階內(nèi)容我還在逐步完善等跑一段時(shí)間再整理出來分享。在你自己實(shí)際用的時(shí)候建議先小范圍跑一條核心業(yè)務(wù)路徑跑通再擴(kuò)不要一上來就全公司鋪開。