网络遥测技术演进:从SNMP轮询到gRPC推送实践

📅 发布时间:2026/10/21 17:31:10
网络遥测技术演进:从SNMP轮询到gRPC推送实践
网络运维这行有句老话数据采集是一切监控和自动化决策的地基。相信做过网络监控的同行几乎都被 SNMP 折腾过——配好 community翻着 MIB 找 OID写脚本定时去轮询设备最后拿到的数据不是粒度太粗就是刚抓完就已经过期。这几年“网络遥测/Telemetry”逐步从概念走向一线把原来“定期去问设备要数据”的模式完全翻了过来不需要反复去拉取了让设备按需把数据流式推给采集端。而这套演进里从 SNMP 到 gRPC 是一条非常清晰的主线也是这篇文章想完整拆解的内容。这篇文章会从 SNMP 的轮询原理讲起分析它为什么在高频、精细化监控场景下会撞到天花板再讲 Telemetry 的“订阅-推送”思路是怎么形成的gRPC 又凭什么成为承载遥测的主流协议接着把 gRPC 遥测的工作原理、订阅模型、数据编码、部署模式一层层拆开再补上我从实际项目中整理出来的配置要点、参数选型和故障排查经验。不管你现在是在做监控系统选型还是准备把手里的网络设备逐步接入 Telemetry这篇文章都值得你从头到尾读一遍。1. SNMP 时代轮询架构的天花板在哪里1.1 轮询模式的底层逻辑SNMP 诞生于上世纪八十年代当初设计的目标很直接用一套尽量轻量的协议把路由器、交换机、主机等网络对象的状态信息统一管起来。它最核心的工作方式可以用一句话概括——请求-响应模型加主动告警。监控端作为主动方周期性地发送 GET 请求设备收到请求后在 MIBManagement Information Base里查找对应的 OID再把结果返回。除此之外还有一个 Trap 通道设备在事件发生时主动向监控端发送告警但 Trap 是单向的、不可靠的没有确认机制中途丢包只能随它去。从设计取舍来看SNMP 刻意保持了“轻”这个特点。它走 UDP端口 161 用于查询162 接收 Trap报文结构紧凑对设备 CPU 和内存的开销都很小。在那个网络设备性能紧张、带宽按 kB 计量的年代这个选择非常合理。但问题恰恰出在这种“轻”上UDP 不保证传输可靠轮询意味着数据的时效性被一个固定周期给锁死了。只要你把监控系统接上一个网络规模稍微大一点的环境就会发现每台设备、每个接口都在被轮询监控服务器隔一段时间就要把请求重新发一遍。举一个非常经典的场景你盯着核心交换机的出接口流量SNMP 轮询周期设置成 60 秒。某一次突然出现持续 10 秒的突发拥塞但下一轮 GET 请求到达时突发已经结束数值回归正常监控曲线只看到一个不明显的毛刺甚至什么都没有。反过来如果为了捕捉这种突发把轮询周期压到 5 秒那么上千个接口的轮询请求会像轰炸一样打到设备上设备的 CPU、管理进程、网络带宽一起上涨监控平台自己也要处理海量请求响应整个系统的性价比会变得很差。1.2 数据冗余和 MIB 结构的困局除了时效性之外SNMP 另一块短板出现在数据冗余和模型结构上。用 SNMP 轮询时你想要的数据往往就集中在接口流量、丢包计数、CPU 利用率这几个点但实际实现中却要把一棵子树上的一堆指标一起拉下来或者在一个表格里翻半天才能找到真正关心的条目。MIB 的对象树是历史沉淀出来的大量早年间定义的节点和字段已经不再适合现在的监控需求而新功能、新指标又迟迟没有标准化的 OID很多只能靠厂商私有 MIB或者干脆取不到。更重要的一点是SNMP 的数据模型是偏向“瞬时状态”的它适合表达“设备上某个指标此刻的值”但很难表达带上下文、带时间序列的数据。你通过轮询拿到的是一堆彼此孤立的快照想知道某条链路从什么时候开始丢包、丢包率随时间怎么变化、丢包和流量峰值之间有没有联动就只能自己把这些快照按时间存进数据库再做二次关联计算耗费大量存储和计算资源最终得到的还只是一个粗糙的近似图景。1.3 一次真实的丢包排查经历我在排查数据中心某条链路丢包问题时就有过一段被 SNMP 卡住手脚的经历。两台设备之间的链路时延和丢包率明明已经有点异常了可监控平台上 SNMP 拿到的接口 CRC 错误计数和丢包统计一直很正常。后来通过设备命令行手工查询才发现光模块的误码率、接收光功率这类底层的物理层指标压根没有暴露到标准 MIB 里系统里存了数据但采集协议够不着它。最后只能靠人工在设备上敲命令看输出监控平台完全成了摆设。这种“设备里明明有数据但采集系统就是拿不到”的憋屈感很多做网络监控的朋友应该都有过。它本质上反映的是旧协议的设计边界模型封闭、抽象层次低、采集模式被动。当网络规模和监控要求同步上涨以后继续在 SNMP 上打补丁已经不够了业内开始酝酿一个更根本的改变——从“让监控端来问”变成“让设备主动推”。2. 从轮询到推送Telemetry 的技术演进路径2.1 遥测的核心思想从“拉取”到“订阅”遥测Telemetry这个词并非网络行业原创它最早来自航天和工业遥测领域指的是对被测量对象的参数进行远程采集和传输。放到网络背景下它的核心思想可以浓缩成一句话数据从“被拉取”变成“被推送”从“周期快照”变成“持续数据流”。在 SNMP 时代监控端是发起者设备永远是被动响应者。到了 Telemetry 时代角色完全反转过来设备变成主动发送方监控端只需要在建立会话时定义好订阅内容——要订阅哪些数据路径、采样频率是多少、触发方式是什么。设备端持续按照订阅要求把数据流式推送过来中间没有反复的 GET 请求没有频繁的请求-响应交互连接建立以后就是一条持续的数据管道。这个转变彻底解决了 SNMP 面临的三个核心痛点。第一数据时效性大幅提升采样间隔可以轻松压到秒级甚至亚秒级不用再担心高频轮询带来的开销第二设备端可以基于事件推送比如接口状态变化、路由表变化、资源利用率越过阈值事件发生的那一刻就把数据推出来而不是等下一个轮询周期才看到第三数据模型走向结构化、标准化开始用 YANGYet Another Next Generation模型描述“设备上到底有哪些数据、数据长什么样、层级关系如何”而不是像 MIB 那样各家自己定义、谁也说不清谁。当然理念归理念落到工程上还必须解决协议载体的选择用什么协议来承载这种流式推送数据这条演进路线上出现过不少候选方案最终 gRPC 成了网络遥测领域事实上的主流方向之一。理解 gRPC 为什么能胜出才能真正明白 Telemetry 的工作原理为什么是今天这个样子。2.2 gRPC 凭什么成为遥测的主流承载协议在分析 gRPC 之前先得承认一个事实gRPC 并不是专门为网络运维设计的协议。它底层基于 HTTP/2序列化格式用 Protocol Buffers简称 protobuf最初主要用在微服务之间的服务调用上。但它的很多底层特性放到网络遥测场景里几乎是天生的绝配。第一是原生支持流式传输。gRPC 支持四种调用模式一元请求、服务端流、客户端流、双向流。遥测采集属于典型服务端流客户端发起一次订阅请求服务端设备持续往同一条流里写数据连接保持长期不关闭。这种长连接能力是 HTTP/1.1 那种“一次请求一次响应响应完就断开”的模型完全不具备的。SNMP 每一次 GET 都要走一次完整消息交换而 gRPC 一旦建好连接设备可以不断把数据推过来中间的额外开销非常小。第二是二进制序列化带来的高效率。遥测数据的典型特征是字段多、结构嵌套、数值密集。如果用 JSON 这类文本格式传输一条接口统计记录可能有几十个字段报文字节数比二进制格式多好几倍解析时 CPU 开销也大。protobuf 采用紧凑的二进制编码字段名在编码时被映射成数字标识整型数据用变长编码优化省掉了大量重复的字符串内容同样的数据在网络上传输的体积小一个数量级。在大规模设备同时上报的场景下这个优势会被放大得非常明显。第三是 HTTP/2 的多路复用和流控机制。一条 gRPC 连接上可以承载多条独立的流每条流都有自己的状态和收发窗口互不阻塞。这意味着在一台设备上同时订阅接口统计、路由表状态、资源利用率三类数据时它们可以并行传输不会挤在同一个队列里互相拖慢。SNMP 面对同类场景时只能依次请求表现也差得多。第四是生态集成度。gRPC 有官方库覆盖几乎所有开发语言采集器端用 Go、Python、C、Java 都可以protobuf 定义好接口后自动生成代码省去大量手工协议处理工作。反观 SNMP 生态开源库虽然也不少但处理 BER 编解码、编译 MIB 都比较麻烦还要自己兜住 UDP 的不可靠性。2.3 SNMP 与 gRPC 遥测的关键差异对照用一个表格把两代技术放到一起对比看得更直观。维度SNMP 轮询gRPC 遥测传输层UDP不保证可靠TCP HTTP/2可靠传输数据获取方式请求-响应监控端主动拉取订阅-推送设备端持续推流数据编码BERASN.1 二进制Protocol Buffers 二进制数据模型MIB / OID标准化程度偏低YANG 模型结构化、可扩展数据粒度受轮询周期限制通常数十秒起步秒级、亚秒级、事件级扩展性私有 MIB 多跨厂商融合困难模型定义规范跨厂商统一性更好连接模式每请求一交互无长连接HTTP/2 长连接双向流典型开销轮询脚本加请求响应交互一次订阅持续推送这张表并不是说 SNMP 一无是处。在轻量查询、简单设备状态获取、老旧设备兼容这些方面SNMP 今天还有不可替代的位置现实中绝大多数监控系统仍然把它作为兜底手段。但当你需要精细化、大规模、高时效的网络监控时SNMP 这个底座确实撑不住了gRPC 遥测的价值才会真正凸显。3. gRPC 遥测的核心工作原理拆解3.1 一条连接、一条数据流gRPC 遥测的工程架构可以分成三个层面来理解。最底层是传输和序列化层由 gRPC 框架本身提供负责连接的建立与维护、消息的编码解码、流控以及错误处理。中间是数据模型层由 YANG 模型定义负责表达设备上有哪些可采集的数据、数据之间的层级关系、各字段的具体含义。最上层是订阅服务层对应 gRPC 暴露的 RPC 服务接口常用的是订阅管理和数据推送两类接口。在实际运行中设备端作为 gRPC 服务端对外暴露订阅服务采集器作为 gRPC 客户端发起订阅请求请求里会带上要订阅的传感器路径、采样周期、触发模式等参数。设备端收到订阅请求后把它注册到内部的采样引擎中按照策略周期性地读取对应数据封装成消息写入 gRPC 流。数据到达采集器端后经过解码、解析、汇聚最终落到时序数据库或流处理平台再被监控告警、分析应用消费。这个过程用点外卖来类比最清楚你不是每隔几分钟打电话去问厨师“菜做好了吗”而是在下单时就定好菜品和送达时间后厨按节奏做做好就直接送过来。SNMP 是前者gRPC 遥测是后者。核心变化在于交互次数被压低到了极限数据到达的时效性却因为“主动推送”变得更高。3.2 订阅的三个关键维度路径、采样、触发要真正做好遥测采集订阅参数的配置是一门基本功。这里的“订阅”不是在界面上勾选一个指标名称而是有三层配置维度采样路径、采样周期、触发模式。采样路径sensor path指向 YANG 数据模型树里的具体节点。比如你想采集接口统计订阅的路径就是某个接口组下的 counters 子树想采集路由表就订阅路由状态子树。YANG 模型最大的好处是路径定义清晰设备会明确声明支持哪些路径跨产品线之间路径可以对齐采集脚本不用针对每种设备单独开发。我建议在做采集前先梳理一遍设备支持的 YANG 路径清单把它当成 API 文档来用而不是靠经验猜。采样周期决定了数据推送的频率。周期越小数据实时性越好但设备端采样开销、网络带宽占用都会明显上升。当订阅数量很多时设备的 CPU 会显著吃紧。我的经验是大部分指标从 10 秒到 60 秒起步只有真正需要快速响应关键业务指标才压到 1 到 5 秒不要一上来就想把所有指标全部高频接入那样代价会很高。触发模式通常有三种周期推送sample、变化即推送on-change、以及两者结合。周期推送最简单到点就上报一次。变化即推送适合接口状态、配置变更、路由收敛这类“低频率、高价值”的事件型数据数据不变就不推一旦变了立刻推。还有一种降噪设计叫抑制suppression机制当数值变化极小或低于某个阈值时不推送但为了防止长期静默又设置一个最大静默时间超过时间强制上报一次避免采集端永远等不到更新。3.3 数据通道方向dial-out 与 dial-ingRPC 遥测在实际产品中有两种部署模式业界的叫法是 dial-out 和 dial-in。理解它们的区别对齐网络架构和安全策略非常有帮助。dial-in 模式是指采集器主动向设备发起 gRPC 连接并订阅设备端被动接受。这种模式很直观监控平台管理连接的目标设备侧只需要配置好将自己的服务端口开放给采集器即可。它的优点是便于集中管理连接由中央侧发起采集器可以自主决定何时订阅、订阅什么。缺点是在设备数量非常庞大时采集器要维护大量的并发连接还要负责处理设备不可达、连接中断、重复连接等各种异常情况连接健康管理会成为一项额外负担。dial-out 模式则反过来由设备主动向采集器发起连接并推送数据。设备侧会预先配置采集器的地址、端口、订阅路径到时间就会主动建立 gRPC 连接把数据推送到远端。这种模式很适合安全边界严格的网络环境设备位于内部网络采集平台是独立收集节点设备主动外联可以避开在防火墙上大量开放入站端口的麻烦。我把两种模式放在一个场景里对比如果采集平台数量少、网络区域可控选 dial-in 管理最省事如果设备分散、跨区域或者安全策略限制严格dial-out 更合适。两种模式底层用的订阅语义和编码逻辑是一致的只是连接的发起方向不同。在做采集器开发时需要留意自己处理的是 gRPC 客户端还是服务端别把方向搞反了这是新手最容易踩的第一个坑。3.4 编码方式、心跳机制和连接保活前面提到 gRPC 遥测默认用 protobuf 编码但工程实践里并不是只有这一种选择。主流设备的实现一般同时支持 JSON 编码和 protobuf 编码。JSON 的好处是调试直观人用工具也能直接阅读代价是体积和解析开销都大protobuf 的好处是传输和解析高效但调试时要先配好对应的 .proto 文件否则看到的是一堆十六进制乱码。我的建议是调试和验证阶段先用 JSON方便定位问题生产环境稳定后切换到 protobuf让它长期跑着压资源把性能优势发挥出来。长连接还有一个容易被忽略的细节心跳。gRPC 流有自己的 HTTP/2 连接保活机制但如果网络路径中间设备静默丢弃了长时间空闲的连接TCP 层面不会立刻感知。设备端在遥测设计里通常会周期性地发送一个内部定义的心跳或元数据消息告诉采集端“我还活着”。如果采集端在约定时间内没收到任何有效遥测数据就应该主动判定会话异常并执行重连。这句话请每个做遥测采集器的人都认真对待我在后面的故障排查部分还会再回到它。4. 从零搭建一条 gRPC 遥测采集链路4.1 设备端配置项与最佳实践设备端把遥测引擎打开无非是儿步操作但每一步都有隐藏细节。不同厂商的命令和工具差异较大我在这里用一套通用的配置思路来还原整体流程具体命令请对照你手头设备的官方操作手册。基本流程是先开启 telemetry 引擎整体开关再创建采集器配置包括远端地址、端口、传输协议类型gRPC 或 gNMI、认证方式TLS 证书或用户名密码然后创建订阅组并把采样路径、采样周期、触发模式绑定进去最后把订阅组绑定到采集器配置上生效。这里要特别提醒一个隐蔽的坑部分设备的 telemetry 引擎默认是不加载的而且它和普通 SNMP 进程是独立的。配置写完后务必用 show 命令确认引擎进程已启动、连接状态是 established。不要只看配置还在就以为任务完成了。我见过不少案例配置看着完全正确但一直没有数据推出来最后排查到根因是引擎根本没启动前前后后浪费了很长时间。TLS 证书问题同样容易在生产环境里卡住。gRPC 遥测默认支持加密传输设备端向采集器推送数据时需要校验服务端证书。测试环境可以用自签证书先把链路跑通但生产环境建议尽早纳入正式的证书管理流程。证书配置错误时设备不一定打印明显的错误提示可能只在日志里反复刷连接失败这时候如果没有一边抓包一边翻日志排查起来会非常吃力。4.2 采集器端实现思路和编码细节采集器侧的实现我用 Python 的 grpc 库写下核心的订阅加接收循环作为示意代码结构大概是这样的import grpc import telemetry_pb2 import telemetry_pb2_grpc channel grpc.insecure_channel(collector-endpoint:port) stub telemetry_pb2_grpc.TelemetryStub(channel) request telemetry_pb2.SubscribeRequest( sensor_pathinterfaces/interface/statistics, sample_interval10000, # 毫秒 ) for telemetry_data in stub.Subscribe(request): process(telemetry_data)这个 for 循环是阻塞式的每收到一条数据就会交给 process 处理。如果业务要求精确的一次性语义还需要在 process 之前做幂等去重。不过更关键的一点是不要把接收、解码、入库全部塞进同一个线程。接收循环一旦被耗时操作卡住gRPC 内部的缓冲队列就会被占满并触发背压机制最终表现为自动断流采集端看起来就像“没有数据”或者“数据延迟突然变大”。正确做法是接收线程只负责把原始消息丢进队列解码和入库交给独立的工作协程或线程池去处理。在数据入库这一层我推荐用支持高基数标签的时序数据库把设备名、接口名、订阅路径作为标签存储。这样后续做告警和图表时可以按任意维度做聚合和筛选非常灵活。数据的保留策略也要提前设计好原始高频数据保留短期比如 7 天中间做一次降采样把 1 分钟均值保留 30 天长期可以保留 5 分钟均值或 1 小时均值。分级保留能极大缓解存储压力。4.3 部署前必须想清楚的五个参数gRPC 遥测正式部署前有几个参数我建议提前认真做取舍否则上线后必定要返工。采样周期要分级配置。关键业务指标可以用 5 秒、甚至 1 秒的高频周期普通指标 30 秒到 60 秒足够。一次订阅里如果包含了大量 sensor path设备端是按周期统一采样的周期太短会让设备 CPU 明显上升。我建议先做几台设备的小范围验证观察设备负载再定全局策略。编码类型尽量生产环境用 protobuf。联调期用 JSON 调试没问题但长期跑还是二进制格式省资源尤其是设备数量上来以后带宽和解析 CPU 的差距会变得非常可观。流数量要控制。一台高密度设备可能同时承载几十个订阅流虽然 gRPC 的 HTTP/2 支持多路复用但每个流都是有内存上下文的流多了设备端的内存和 CPU 同样会跟着上涨。存储保留策略一定要提前设计。遥测的数据频率远高于 SNMP 时期如果继续用老式点表存储结构磁盘和索引都会快速膨胀。时间序列数据库的压缩策略和降采样策略必须一开始就搭好。网络带宽要按峰值规划。几百台设备同时以 10 秒周期推数据汇聚到采集平台的流量是 GB 级/天的规模。监控网络不能只看平均流量要看峰值并且留出至少 30% 到 50% 的余量避免在突发故障时丢数据。5. 遥测落地中的高频故障与排查经验5.1 采集断流最多见也最迷惑的问题采集断流是我在遥测落地过程中遇到最多的故障类型。现象通常是设备日志显示 gRPC 连接已经建立采集端也看到一个连接存在但持续收不到数据或者运行一段时间后连接自动断开。遇到这种情况我的排查顺序是这样的。 第一步确认设备端遥测引擎进程还活着有没有被 CPU 消耗殆尽。 第二步在设备侧打开遥测流的调试抓包确认 gRPC 流上到底有没有数据在发。 第三步检查协议层面的错误TLS 证书是否过期、证书域名是否匹配、认证方式是否配对得上。 第四步检查采集器端解析模块有没有异常异常频繁时 gRPC 可能会主动终止连接。 第五步检查 HTTP/2 流的相关限制参数比如最大帧大小或最大并发流数部分设备的默认限流参数比较保守数据量一上来就会触发保护。我还遇到过一个非常典型的“隐性断流”场景设备端和采集器之间的路径上有一台防火墙它会把长时间空闲的 TCP 连接静默丢弃两边却完全没有感知。业务上看似还连着实际上数据流早就被掐断了等到需要数据时才发觉链路已经死了。解决办法就是在应用层配置心跳探测发现心跳超时就主动重连不要依赖 TCP 层给你报错。5.2 订阅失败或数据为空多半不是玄学订阅失败最常见的原因是 sensor path 写错或者当前设备根本不支持那条路径。YANG 模型虽然做了不少统一化但不同系统对路径的实现并不完全一致就算功能名称相同路径的层级也可能有差异。排查方法很朴素从设备支持的路径列表里把目标路径查出来再原样复制到订阅配置里别手敲代号敲错一个符号设备端的响应就会不一样。数据为空则要看采样模式。on-change 模式下如果指标一直没变化设备端不会推任何数据这本身是预期的不是故障。这时候可以先把触发模式切到 sample确认数据通道没问题再切回 on-change。如果切到 sample 仍然没有数据那就要回头检查采样路径的筛选条件是不是把目标对象过滤掉了。5.3 数据乱序、重复和时钟问题数据乱序对实时监控的影响不大但画图表时会出现时间倒退的怪象。gRPC 长连接上的流式传输理论上可以保证到达顺序可一旦采集器端用了多线程处理入库的顺序就可能乱掉。解决办法是在解析层给每条数据标注一个单调递增的序列号入库前做一个小的排序缓冲再写入。如果设备端没有提供序列号用采集端本地时间戳排序也能凑合但是要与设备时钟对齐否则跨设备对比会出问题。重复数据则经常出现在断线重连场景。设备端在断线期间可能缓存了一批遥测报文重连之后会一次性推送过来形成补发如果上游没有做去重统计数字会出现虚高。对实时告警来说这影响不大但对做精准流量统计或计费分析的场景就需要在采集层做幂等过滤用唯一标识加时间窗口过滤重复记录。我把这个细节放在故障列表里不是因为它常见而是因为它最隐蔽。5.4 一组实测数据gRPC 遥测与 SNMP 轮询的开销对比最后分享一组我实测过的同一台核心交换机的接口统计采集对比。SNMP 轮询接口计数周期 60 秒单次响应耗时约 80 毫秒一个完整周期内大概取到 20 条数据换成 gRPC 遥测同样的路径采样周期设为 10 秒设备端流式推送采集器端解码解析 100 条记录总耗时才不到 30 毫秒。这组数据说明了什么在低频场景下SNMP 还能勉强支撑但一旦把采集频率压到秒级SNMP 的开销会快速放大到不划算。遥测把单次采集开销摊薄到了持续流里用固定的一次性连接成本换来持续稳定的数据流这种设计才适合今天动辄成百上千台设备的网络规模。如果你正在做新旧监控方案的切换评估可以按这个思路先测一组数据用实际开销说话会更有说服力。我在实际项目中折腾过不少次断流、证书、路径错误之类的问题总体感觉是gRPC 遥测的上手门槛并不高但生产落地要把协议细节和运维习惯一起调整过来。最后再分享一个小技巧上线初期可以在采集平台一侧把每条订阅都打上唯一标识和设备的连接日志做关联查询这样一旦出现断流、丢订阅定位起来会快很多。这套从 SNMP 到 gRPC 遥测的迁移路径我自己走得不算轻松但回报是实打实的——监控数据终于跟得上网络的真实状态了。