遥测与推送
课程(6 节,按顺序学)
① SNMP 用了二十年,为什么要换
入门 · 约 9 分钟
本课目标:搞清从轮询走到流式推送不是「换个协议」,而是绕过三个数学上无法克服的限制。
轮询做的是什么
管理站每隔 T 秒去问设备一遍:「这几百个 OID 现在的值是多少?」
★ 听起来没问题,而且它确实撑了二十多年——因为过去链路是百兆的、5 分钟的粒度够用。
★★ 但速率涨了三个数量级之后,这个模型开始在三个地方同时崩掉。
★★★ 限制一:采样间隔决定了你能看见什么
一次 3 秒的 10Gbps 突发,按 30 秒轮询会被平均成 1Gbps——低估 10 倍。
★★★ 而危险在于图上确实有个凸起,所以你不会怀疑数据,反而会得出「峰值 1Gbps,链路还很空」这个完全错误的结论。
★ 这不是「精度不够」,是结论反了。
★★★ 限制二:32 位计数器 3.44 秒就绕一圈
32 位的容量是 4.29GB,而 10Gbps 就是每秒 1.25GB —— 4.29 / 1.25 ≈ 3.44 秒。
★★ 按 30 秒轮询,两次之间它绕了 8 次多,差值根本不代表流量。
★ 这条限制光调间隔解决不了:要在 10G 口上不回绕,得压到 3 秒以内——而那已经超出轮询能承受的范围了。
★★ 限制三:想看得细就会把设备打挂
轮询开销和间隔成反比:间隔减半,负载翻倍。而 SNMP agent 和路由协议抢同一颗 CPU。
★★★ 于是「看得更细」和「设备别挂」是直接矛盾的两个目标——每台设备都有一个「最快只能到几秒」的硬下限。
★ 去②负载页看:这台设备的 SNMP 下限是 4 秒,而你想看清那个 3 秒的突发需要 3 秒。差一点,但过不去。
推送是怎么同时解决这三条的
★★★ 关键不是「更快」,而是把「谁决定采样时刻」从管理站交给了设备:
· 没有请求-响应往返 → 间隔能压到亚秒级(限制一、三)
· 时间戳由设备打 → 算速率不用猜间隔(抖动消失)
· 状态类可以「变了才推」 → 稳态零开销 + 毫秒级通知(限制三)
★ 所以这是换了一种做法,不是同一件事做快一点。
实验重点
- ★★★ 轮询有三个绕不过去的限制:采样间隔决定可见性、32 位计数器回绕、开销与间隔成反比。
- ★★ 推送真正改变的是「谁决定采样时刻」——交给设备之后,上面三条同时松开了。
- ★ 其中两条光把间隔调小解决不了,所以「看得更细」有时意味着换机制。
② ★★★ 一个公式:观测峰值 = 真实峰值 × (时长 / 间隔)
入门 · 约 10 分钟
本课目标:把混叠算清楚,并且分清「计数器被平均」和「状态被错过」这两种完全不同的失真。
先看那个公式
对计数器来说:观测峰值 = 真实峰值 × (事件时长 / 采样间隔)(不超过 1 倍)。
★ 代进一次 3 秒的 10Gbps 突发:
· 间隔 1 秒 → 看到 10 Gbps(完整)
· 间隔 10 秒 → 看到 3 Gbps(低估 3.3 倍)
· 间隔 30 秒 → 看到 1 Gbps(低估 10 倍)
· 间隔 300 秒 → 看到 0.1 Gbps(低估 100 倍)
★★★ 为什么「看得见但数值假」比「看不见」更危险
看不见的话,你会去查、会怀疑数据。
★★★ 但一个看起来合理的假数字你不会怀疑。「峰值 1Gbps、10G 链路、还很空」——这个结论自洽、可信、而且完全错误。
★ 现实后果:交换机的丢包计数器在涨,而流量图上明明离满还很远,于是排障方向整个走偏。
★★ 而状态和瞬时量是另一套逻辑
★★★ 计数器会累积(字节数还在,只是被摊平了),而状态和瞬时量不累积——采样发生在某个瞬间,要么正好撞上,要么完全错过。
★ 所以状态类没有「平均值」这个中间态:
一次 2 秒的闪断在 60 秒轮询下,撞上的概率是 2/60 ≈ 3.3%,也就是 97% 的概率一点痕迹都没有。
★★ 把这两种混为一谈(比如给闪断也算个「平均值」)会得出荒谬的结论。
微突发:秒级采样也看不见的东西
★ 交换机缓存溢出往往发生在毫秒级的微突发上。按上面那个公式,1 毫秒的突发在 1 秒采样下也要低估 1000 倍。
★★ 所以微突发在任何基于「采样」的手段下都是看不见的——要抓它只能靠设备侧的缓存占用高水位或者丢包计数器,而不是流量图。
实验重点
- ★★★ 计数器:观测峰值 = 真实峰值 × (时长/间隔)。30 秒采样下 3 秒突发低估 10 倍。
- ★★★ 状态/瞬时量不累积,没有「平均」这个中间态——要么撞上,要么完全错过。
- ★★ 「看得见但数值假」比「看不见」更危险,因为你不会去怀疑一个合理的假数字。
③ ★★★ 32 位计数器在 10G 口上 3.44 秒绕一圈
进阶 · 约 8 分钟
本课目标:算一遍回绕时间,并理解为什么这条限制光调采样间隔解决不了。
算一下
32 位计数器的容量是 2^32 字节 = 4.29 GB。
10Gbps 就是每秒 10e9/8 = 1.25 GB。
4.29 / 1.25 ≈ 3.44 秒 —— 跑满线速时每 3.44 秒绕一圈。
换成别的速率
· 100 Mbps → 5.7 分钟(还能忍)
· 1 Gbps → 34 秒
· 10 Gbps → 3.44 秒
· 100 Gbps → 0.34 秒
· 400 Gbps → 0.09 秒
★★★ 也就是说 400G 口上的 32 位计数器,每秒绕十几圈——任何采样都读不出有意义的差值。
★★ 回绕在数据上长什么样
表现是「计数器突然变小了」。
★ 而工具怎么处理这件事各不相同:
· 有的当成设备重启(于是丢弃这个数据点)
· 有的直接算出一个负速率
· 有的加上一个 2^32 试图补偿——但绕了几圈根本无从得知,所以这种补偿只在恰好绕一圈时才对
★★★ 关键结论:一旦采样间隔超过回绕时间,这个数据在任何后处理下都无法恢复。
解法只有一个方向
★ 64 位计数器(SNMP 里是 ifHC* 那一套,OpenConfig 本来就都是 64 位):
· 10G 口上要 468 年才绕一圈
· 400G 口上也有 11.7 年
★★★ 注意这条限制不能靠调间隔绕过:要在 10G 口上避免回绕,间隔得压到 3 秒以内,而那已经超出轮询能承受的范围(本设备下限 4 秒)。所以答案是换计数器,不是调参数。
实验重点
- ★★★ 32 位容量 4.29GB ÷ 10Gbps 的 1.25GB/s = 3.44 秒回绕。100G 口上只有 0.34 秒。
- ★★ 回绕过的数据无法后处理恢复——因为「绕了几圈」这个信息本身就丢了。
- ★ 解法是 64 位计数器(10G 口上 468 年),而不是把采样间隔往小调。
④ ★★★ 状态用 ON_CHANGE,计数器用 SAMPLE
进阶 · 约 9 分钟
本课目标:掌握订阅模式的选择规则,并理解为什么配反的后果是不对称的。
先分清数据的性质
· 计数器(字节数、包数)→ 单调递增,每个包都在变
· 状态(接口 up/down、BGP 邻居状态)→ 平时根本不变,一天几次
· 瞬时量(CPU、温度、光功率)→ 上下波动的当前值
★ 这个分类不是学术划分——它直接决定该用哪种订阅模式。
★★★ ON_CHANGE 为什么是状态类的完美答案
「只在值真的变了才推」,于是同时拿到了两个平时互相矛盾的东西:
· 省:稳态下流量接近零(什么都没变就什么都不发)
· 快:一变化就是毫秒级通知,不用等任何周期
★★★ 而轮询在这两件事上必须取舍:想快就得密,密了就贵。ON_CHANGE 直接跳出了这个取舍。
★ 对比那个 2 秒闪断:轮询 97% 概率错过,ON_CHANGE 必然完整记录两条(down 和 up)。
★★★ 但配反的后果是不对称的
· 状态配成 SAMPLE → 白问几万次(答案都一样)+ 变化要等一个周期。浪费又慢,但不会出事。
· 计数器配成 ON_CHANGE → 计数器每个包都在变,等于要求设备每个包推一次。★★★ 这会把设备和收集器一起打死,是个能直接造成事故的配置错误。
★ 所以订阅设计的第一步永远是:先分清这个叶子是计数器还是状态。
现网是混合订阅
★ 一台设备上通常是多个订阅并存:
· 状态叶子 → ON_CHANGE
· 计数器叶子 → SAMPLE,间隔按需要抓多细的突发来定
· 瞬时量 → SAMPLE,间隔按变化速度定(温度几分钟,CPU 要秒级)
★★ 而 TARGET_DEFINED 把这个判断交给设备,省心,但不同厂商可能判断不一样——同一份配置在两家设备上行为不同,排障时很难查。
实验重点
- ★★★ 规则:状态用 ON_CHANGE(省且快),计数器用 SAMPLE(它每个包都在变)。
- ★★★ 配反的后果不对称:状态用 SAMPLE 只是浪费;计数器用 ON_CHANGE 会打死设备。
- ★ 现网是混合订阅,一台设备上多种模式并存,不是二选一。
⑤ ★★★ 监控自己造成了故障
排障 · 约 9 分钟
本课目标:理解「轮询不是只读所以无害」这个误解的代价,以及正确的应对顺序。
事故剧本
★★★ 这个剧本在现网反复出现:
① 出了一次说不清的问题,觉得「监控粒度太粗」
② 把轮询间隔从 5 分钟调到 30 秒(感觉只是「细 10 倍」)
③ 设备控制面 CPU 打到 100%
④ BGP 邻居掉线、BFD 误报、路由大范围收敛
⑤ 而收敛本身又消耗控制面 → 更糟 → 正反馈
为什么轮询这么贵
一次 GetBulk 往返,设备要做的事:解析 PDU → 按 OID 遍历 MIB 树 → 逐个取值 → 编码回去。
★★★ 全程在控制面 CPU 上,而且和路由计算抢同一份资源。
★ 所以「轮询是只读操作,所以无害」是个危险的误解——它是实实在在的负载,而且和最关键的那些进程抢 CPU。
★★ 别忘了收集器那一侧
间隔从 5 分钟调到 10 秒,数据点数量涨 30 倍。
★ 设备可能扛得住,但收集器和时序数据库不一定。而收集器过载的表现和「设备没发」很像(数据有缺口),所以要单独监控收集器的丢弃计数和写入延迟。
★★ 这和 xFlow 模块里那套「三个计数器」是同一个思路:光看发送端不够,得看接收端成功处理了多少。
正确的应对顺序
★★★ 需要更细的粒度时,顺序应该是:
① 先问要看什么事件(多长的突发?多快的闪断?)
② 算出需要多细的间隔(事件时长以内)
③ 看这个间隔当前机制撑不撑得住
④ 撑不住就换机制(gNMI),而不是把同一个机制往极限推
★ 反过来做(先调参数再看效果)就是那个事故剧本的开头。
实验重点
- ★★★ SNMP agent 和路由协议抢同一颗 CPU——轮询不是「只读所以无害」。
- ★★ 收集器那一侧同样会过载,而表现和「设备没发」很像。
- ★ 正确顺序:先定要看什么事件 → 算需要的间隔 → 看撑不撑得住 → 撑不住就换机制。
⑥ ★★★ 推送停了,看起来像「一切正常」
排障 · 约 9 分钟
本课目标:认识流式遥测引入的那个新的失效模式,以及为什么它比轮询失败更危险。
两种失效形状完全不同
★★★ · 轮询失败 → 请求超时,管理站立刻知道,通常还会告警
· 推送停了 → 什么都不来,而「什么都不来」和「什么都没变」在数据上完全一样
★ 于是:设备是 up 的、没有任何告警、图就是一条平线——和「网络很安静」长得一模一样。
★★ 为什么会断
gNMI 跑在一条长连接上(gRPC over HTTP/2)。断的原因有很多:
· 收集器重启 / 升级
· 中间有状态设备(防火墙、NAT)把空闲连接老化掉
· 设备侧订阅进程重启,而没有自动重建
· TLS 证书过期
★ 注意最后两个:设备自己也可能「以为还在推」,所以光在设备上 show subscription 也不一定看得出来。
★★★ 所以必须监控订阅本身
★★★ 上了流式遥测之后要补一条监控:订阅还活着吗。
最实用的做法是心跳式判断:
「过去 N 秒有没有从这台设备收到任何数据点」——没有就告警,不管它是不是「值没变」。
★ 这也是为什么很多平台会给每个订阅配一个低频的 SAMPLE 叶子当心跳:哪怕全是 ON_CHANGE,也要有一条定期来的东西证明管道是通的。
一个更一般的道理
★★★ 这个故障和 xFlow 模块里「收集器缺模板」是同一类:
「我发出去了」不等于「对方收到并看懂了」。
★ 所以监控任何一条数据链路,光看发送端的计数器都不够——必须看接收端成功处理了多少。
★★ 而对监控系统本身来说,这条规则要再加一层:监控系统自己也需要被监控,而且不能用它自己来监控自己。
实验重点
- ★★★ 推送停了是静默的:图是平的、没有告警,和「网络很安静」完全一样。
- ★★ 所以要做心跳式监控:「过去 N 秒有没有收到任何数据点」,而不是等告警。
- ★ 更一般地:「我发出去了」不等于「对方收到并看懂了」——监控系统自己也要被监控。