外观
根因定位
榜单只能说明「这条前缀在抖」,但抖的根因在哪、能不能动手是另一回事:是源头 AS 在反复宣告与撤回(抖动传播到本网)、中段某条传输链路在翻、还是本侧入向对端在抖?三者的处置策略完全不同——源头拒收无用只能告警,近端能断,中段能精确点名链路。
定位把这件事当作 AS 图上的根因定位处理。
代码:app/services/flap_localize.py(纯函数定位器)、prefix_flaps.py 的 localize_flapping(跨节点聚合路径证据)、db/models/prefix_flap.py 的 node_prefix_flap_paths(每 (节点, 前缀) 一行 JSON 存路径证据)。
核心思路:判别性图元差集
把一条前缀的 fleet 路径观测跨节点求并(同 AS_PATH 的 churn 相加、记录哪些节点看到、withdrawn 与 changes 求和),分成抖的路径集与稳的路径集(churn 是否 >0),然后找那个同时满足两条的图元(AS 邻接边、入向对端或起源):
- 载多数 churn;
- 出现在多数抖动路径;
- 且在稳路径里少出现。
它就是嫌疑点。方法参考 Feldmann et al., Locating Internet Routing Instabilities, SIGCOMM'04。
判别流程
折叠 prepend。AS_PATH 里连续重复的 AS(
A B B B C → A B C)是选路手段、不是拓扑跳。不折叠会冒出(X, X)自环边,它只在抖动路径出现故判别分最高,会被误当中段链路——实测某 hub prepend 5 次就产生了这种误判。MOAS 优先。多个不同起源同时出现即路由异常或疑似劫持,绝不自动动手。内嵌进榜行时以行的 origins 为权威(
zone==moas当且仅当行 moas,同一 origin 集算出、结构自洽)。源头强信号。前缀彻底消失(无幸存路径)且窗口内反复 withdraw → 唯一公共点是起源 →
origin。判别性图元。判别分 =
min(churn 质量占比, 抖动路径条数占比) − 稳定占比。两者取小是关键:高介数 hub 在海量路径上当中转,churn「经过它」是拓扑必然(churn 占比高)但只在少数路径(路径占比低)→ 被压低,不背锅。
散布则归源头。没有图元能同时解释多数 churn 和多数抖动路径 → churn 散布、共同点是起源 →
origin。即便有一条备份幸存路径把起源「免责」——多入向齐抖到同一源,病在源侧。起源免责。有稳定路径还到得了起源 → 起源被证明在线,把它及贴着它的边排除出候选,聚焦近端与中段。
四个区与可操作性
| zone | 判据 | 处置 |
|---|---|---|
origin | 全撤回,或多入向散布汇于一源 | 源头侧,拒收无用——只告警 |
near | 抖动集中在同一入向对端 | 可断该 peer,须经会话级门控(见下) |
path | 中段某条 AS 邻接在翻 | culprit_edge=[A,B] 精确点名 |
moas | 多源 | 疑似劫持,绝不自动动手 |
near 用会话级信号门控
真「近端」应当是本节点到该对端的会话也在抖(会话级 flap,来自 runtime 快照、与 flapfeed 完全独立)。
若会话不抖,则那条「churn 集中经某对端」多半是该对端的下游在抖,不是本侧会话——此时 signals.session_flapping=false,置信乘 0.6,标记为不可当断 peer 的依据。门控在端点侧完成(_p0_session_score_by_asn)。
输出
{zone, confidence, culprit_asn / culprit_edge, representative_path, signals}。
representative_path是该前缀 churn 最高的一条 AS_PATH(已折叠 prepend),供前端画路径条、高亮嫌疑段。confidence混合判别分、节点多样性与路径多样性。单节点观测的path天然低置信——一个 vantage point 看不全路径多样性,中段定位多是猜。
内嵌即单一数据源
定位结果内嵌进 GET /ui/fleet/prefix-flaps?group=prefix 每行的可选 localization 对象,与该行同一次查询、同一快照算出。前端不再拼两个接口——按 prefix 对齐 join 两个接口会产生成员集、快照时序、moas 口径三重不一致。
localization=null 表示该行未能定位。顶层 localization_summary 给全量 fleet(含被 limit 截断的部分)的区计数。独立端点 GET /ui/fleet/prefix-flaps/localize 保留供其它用途。
纯只读、只标注不动手。 它是将来自动抑制决策引擎的输入——届时才会用上「near + session_flapping 允许断 peer、origin 只告警、path 精确点名、moas 永不动手」这套映射。
准确度验证
定位算法给出的 zone 与 culprit 没有天然的 ground truth。验证办法是引入与算法本身无关的独立信号,在三重时间尺度上交叉核对:单快照看内部一致性与横向信号、回溯事件日志看持久性、前向复拍看分类稳不稳。
方法可复现;下面的实测数取自一次全量核对,结论随 fleet 状态点在时间上。
验证用的独立信号
| 信号 | 来源 | 验什么 |
|---|---|---|
| 会话级 flap | runtime 快照,与 flapfeed 完全不同源 | near——真近端应伴随会话抖动 |
| 嫌疑点聚集度 | 定位输出的分布形态 | 效度最强的一条:真链路事件会同时命中经过它的一大批前缀;真不稳起源会命中它名下一批前缀。culprit 聚成少数几个即抓到真事件,散成一堆随机边即噪声 |
| 抽样重推差集 | 手工核对 | 「经嫌疑边的 churn」对「绕开它的 churn」,差集是否真的显著 |
| 独立归因管线 | flap_alerts.peer_asn(告警器自己的对端归因,不经定位器) | 与定位器的近端集中点位交叉 |
| 结构一致性 | zone==moas 与行 moas | 应恒成立(行权威) |
单快照:横向信号
- 聚集度分道扬镳,且方向都对。
path前缀高度聚集(实测 61 条前缀只落在 14 条嫌疑边,头一条独占 25 条)——真链路事件的签名;origin前缀高度散布(154 条前缀散在 128 个源,最高才 6 条)——每个末梢网络独立抖动的正确签名,与 path 相反。若定位在乱判,两者不会呈现这种彼此相反的聚散结构。 - 差集显著。 抽样嫌疑边「经它 churn 约 688 / 绕它 churn 约 14」,约 49 倍——边确实在鉴别。
- 结构一致。 271 行
moas判定 0 违例。 - 置信度校准。 多节点观测置信显著高于单节点(path 0.99 对 0.62、origin 0.90 对 0.80)——跨节点佐证正确地抬高了置信。
回溯 72 小时:持久性与独立管线收敛
- 抖动是持久事件,不是快照噪声。
flap_alerts生命周期显示前缀告警平均寿命约 125 min、峰值 open 达 22 h。定位分析的是一个持续数小时的稳定态,单快照因此有代表性。 - 两套独立管线收敛到同一点位。 未经定位器的
flap_alerts.peer_asn,其 open 告警高度集中在同一个高介数 hub 对端——正是定位器把 near / path 结构集中的那个 AS。 - near 被时序重新定性。 该 hub 对端是本网真实 eBGP 对端,72 h 内会话确有数十次抖动,但最近一次早于快照约 13 h。故当前经它到达的 churn 不是会话驱动,而是「穿过它的下游 churn」——定位判
near加低置信、标不可断 peer,恰好对:历史偏抖的对端,但此刻打进来的是下游。near 既非空穴来风,也没被过度断言。
前向:分类稳定性(间隔 25 分钟复拍)
- zone 稳定率 77%,且与置信同序:
path88% /origin80% /near62%。模型越有把握的区,时间上越稳——置信度本身是有效的稳定性预测器。 - 翻转是「低置信 near → 高置信 origin/path」的收敛,不是抖动。 绝大多数翻转形如
near(conf≈0.44) → origin/path(conf≈0.87):near实际是诚实的「我还不确定」过渡态,证据一足就往根因方向落定。若是纯边界抖动,翻转应当置信中性对倒;系统性的低到高说明是证据驱动。 - 嫌疑边跨时间持续。 t0 的 top path 边在同一批前缀上跨 25 min 保持 85–100% 同边——真链路事件签名持续存在。
总评
高置信的 path 与 origin 判断真实且时间稳定,可直接指导处置,尤其是反复出现的中段嫌疑边。near 是被正确标记的低置信过渡区,置信度已经在替操作员区分「能信」与「再等等」,不应据其贸然断 peer。moas 结构自洽。