首页 / 资讯中心 / 文章详情

PLFM_RADAR:统一监控告警平台的设计与实战

PLFM_RADAR:统一监控告警平台的设计与实战 ★ FEATURED ARTICLE
做监控的同学大概都经历过这种夜晚告警群里消息刷得飞快真正致命的那一条却被淹没在99的红色警报里。凌晨两点把值班同事薅起来查问题结果发现是某个接口偶发超时触发了阈值抖动而真正的核心链路已经挂了三分钟没人发现。PLFM_RADAR就是为了解决这类问题而生的一个平台级观测雷达系统。这个名字没少被同事吐槽但我觉得起得挺准。RADAR的本质不是报警而是扫描——持续扫过整个系统的每个服务、每条链路、每台节点发现异常先锁定目标再引导排查方向。PLFM_RADAR就是给平台做的一台雷达。它统一采集全链路的指标、日志和事件通过一套可编程的规则引擎做异常判定和告警降噪最后用服务健康拓扑把故障点在几十秒内定位出来。整套系统从采集到告警再到可视化定位是完全自研落地的前前后后迭代了大半年。这篇文章就把整个项目的设计思路、核心实现、部署调优和踩坑记录都整理出来给正在计划做统一监控平台、或者被现有监控系统狼来了式告警折磨的团队做个参考。1. 项目由来与整体设计思路1.1 为什么需要一台雷达而不是继续堆监控工具先说背景。我们当时的情况是有几十个微服务部署在多个环境里各种监控散落在三四个工具上基础指标看一套自建Prometheus业务日志查ELK链路追踪另开一个系统告警通知则大部分靠Prometheus Alertmanager外加一堆手工脚本。表面上看该有的都有实际用起来问题非常大。第一个问题是数据割裂。指标、日志、追踪各存各的出了故障要来回切换系统看。一次故障排查光是把时间范围在三个系统里对齐就要折腾好几分钟。第二个问题是告警质量差。阈值都是静态配置白天流量大容易误报半夜流量小又漏报。抖动一下就来一条不痛不痒的告警太多真正关键的故障反而被淹没。团队后来养成了看到告警先看是不是误报的习惯这比没有监控更危险。第三个问题是无法从全局视角看到系统的健康状态。几十个服务之间的依赖关系、流量走向、哪里是薄弱环节没人说得清楚。PLFM_RADAR立项时定的核心目标就四条统一数据采集、统一存储模型、统一告警规则、统一可视化入口。说白了就是把原来散落的工具能力收拢到一个平台里并且让告警规则从静态阈值升级为基于业务场景的动态判断。做一台持续扫描、精确定位的雷达而不是一个只会喊狼来了的喇叭。1.2 技术选型与架构决策架构设计上我们一开始就确定了不搞全家桶方案。虽然直接搭一套Prometheus Thanos Loki Tempo的生态也能做到看起来统一但数据模型不一致的问题会一直伴随告警规则的灵活度也受限。所以核心的采集器、存储选型、规则引擎、拓扑计算都做了独立设计。整体骨架是这样的采集端自研的Go采集器Agent部署在每个节点上负责采集系统指标、业务指标、日志摘要并主动上报。选Go是因为部署简单、并发模型好、资源占用低一个Agent跑下来内存占用控制在60MB以内。传输层用Kafka做数据管道扛住采集端的峰值写入同时天然起到削峰填谷的作用。采集Agent只往Kafka写不关心下游消费速度。存储层核心时序存储选用VictoriaMetrics而不是继续用Prometheus。原因后面细说。日志类数据仍写入 Elasticsearch但只保留最近7天的热数据用于告警链路联动查询。规则引擎自研的轻量级表达式引擎支持布尔表达式、聚合函数、持续时间判断、动态基线规则配置存储在MySQL中由引擎定期加载。可视化层基于Grafana做指标看板但服务拓扑图和健康评分是自研的Web组件因为Grafana做不好这种节点关系展示。当时选VictoriaMetrics主要基于三个考量。一是写入性能Prometheus单机写入瓶颈明显VictoriaMetrics的分片和批量写入能力强很多同样的指标量它能扛住更高的写入速率。二是数据压缩率VictoriaMetrics对时序数据的压缩比Prometheus要好同样的磁盘能存更长时间的数据。三是向下兼容PromQL团队已有的告警规则查询语句可以基本平滑迁移。这个选型在后续压测和线上运营中都被验证是值得的。2. 信号采集层统一采集链路的设计与实现2.1 分钟级还是秒级采集频率的差异化设计采集框架设计的第一件事是定义采什么、多久采一次。如果所有指标都一刀切用15秒采集间隔最终结果就是数据量大、存储开销高、但高频指标又看不出细节。PLFM_RADAR把采集对象分成了三个等级在Agent端的配置里用一组策略来定义指标类型采集间隔典型示例存储周期核心业务指标5秒订单量、支付成功率、核心接口耗时原始数据保留7天1分钟聚合保留30天5分钟聚合保留180天系统资源指标15秒CPU、内存、磁盘IO、网络吞吐同上低频汇总指标30秒非核心接口调用量、后台任务执行时长同上核心业务指标用5秒采集是经过一番取舍的。5秒间隔意味着每分钟12个数据点对单接口来说一年就是六百多万个点。如果不做分级存储存储成本根本扛不住。所以我们采用了三层的降采样策略原始数据只保留7天用于故障排查1分钟聚合保留30天用于日常趋势观察5分钟聚合保留半年用于容量规划。这套策略落地后同样的磁盘容量数据可用周期从原来的1个多月拉到了半年以上。Agent端还做了一件事——本地缓存。当Kafka短暂不可用或者网络抖动时采集器不会立即丢数据而是写入本地缓冲文件等链路恢复后再按时间戳回放。这个缓冲和时序数据库里的WAL机制类似对数据完整性非常重要。线上实测中Kafka集群滚动重启导致采集端写入中断的几次情况数据恢复率都做到了100%。2.2 数据模型设计指标、日志、事件的三归一PLFM_RADAR的数据模型是整个系统最核心的设计决策。雷达不能只看单一信号而是要把各种信号融合成一个完整画面。所以我们在数据模型层就把指标、日志、事件三类数据统一到一个通用结构里虽然底层存储不同但对外暴露的查询和关联模型是一致的。每个数据记录由五部分组成时间戳、实体标识、维度标签、指标值、上下文载荷。{ timestamp: 1718966400, entity: service:order-core, labels: { cluster: prod-01, instance: 10.10.8.22, api: /v1/orders, method: POST }, metric: { request_count: 4283, avg_latency_ms: 36.8, error_count: 12 }, context: {} }entity字段是雷达扫描的目标标识labels是可变的维度标签metric是数值型指标。对于日志和事件类数据metric字段则允许为空核心信息放入context载荷中。这个模型带来的直接好处是关联查询变得容易。以前排查接口变慢要先去看监控图确认带宽瓶颈再跳去日志系统查错误日志最后还要手动对比发布记录看是不是上线引起的。现在PLFM_RADAR支持按entity和时间范围一键关联拉取指标趋势、日志摘要、事件记录哪个服务变了、什么时候变的、指标怎么变的、日志里报了什么错一屏看清。排查效率的提升非常明显故障平均定位时间从之前的半小时以上缩短到了十分钟以内。3. 预警引擎规则配置、触发逻辑与告警降噪实战3.1 规则引擎怎么设计才不会三天两头误报规则引擎是整个PLFM_RADAR里迭代次数最多的模块。第一版我们想得很简单——配置指标超过阈值就告警跟Prometheus的告警规则没什么区别。结果上线第一周就被告警疲劳打脸了某支付接口在促销时段请求量翻了五倍响应耗时P99从80ms涨到200ms超阈值告警哐哐地发。但实际上服务处理能力完全正常只是流量起伏带来的正常的排队效应。静态阈值根本区分不了真实故障和正常的业务波动。后来我们把规则引擎从单点阈值判断升级成了场景化条件判断。一条规则由数据源、条件表达式、持续时间、告警级别、接收对象五要素构成。关键是条件表达式支持组合逻辑和聚合函数不再局限于指标 数字这种写法。规则配置的逻辑结构大致是这样规则名: 订单服务-错误率突增 数据源: metric(error_rate{serviceorder-core}) 条件: rate(error_rate[5m]) 0.05 AND request_count 100 持续时间: 3个采样周期 级别: P1 接收人: group:订单研发组, group:值班组这条规则的含义是不仅要求错误率超过5%还要求请求量大于100以免零星流量产生抖动同时这个状态要连续维持三个采集周期才触发告警。持续时间条件把毛刺型波动直接过滤掉了实测下来误报率降了六成以上。比较难的是动态基线告警。很多指标没有固定的合理区间比如凌晨三点的请求量和晚上八点完全不同。静态阈值要么在高峰误报要么在低谷漏报。PLFM_RADAR实现了一个简单的动态基线模块对同一个指标按星期几小时建立历史分布区间用过去30天的数据算出均值、P5和P95实时数据如果超出P95的三倍标准差区间才判定为异常。这个逻辑本身不复杂但效果非常好夜间漏报的问题基本解决了。3.2 告警降噪怎样让值班组不骂人规则引擎能出结果之后我们很快遇到了第二个问题——告警风暴。某个上游依赖挂了下游所有服务的错误率全都飙起来按服务维度配置的规则就会瞬间产生几十条告警。值班同学凌晨三点被四十条短信轰炸谁都会崩溃。告警降噪在PLFM_RADAR里是独立的一套机制从四个层面逐层过滤分组聚合多个服务同时报同一个根因时聚合成一条告警。比如Redis集群故障导致三十个服务超时规则引擎会把这些告警合并成一条redis-cluster-prod异常导致30个服务错误率上升而不是三十条独立告警。告警抑制上游服务已经处于P1告警状态时下游服务触发的同类型告警自动降低级别。这是为了避免一个故障全链路报警的雪崩效应爆炸半径控制在根因节点附近。静默窗口支持按时间段静默。每周定时任务执行期间某些指标的规则自动暂停判定避免脚本跑批期间的正常资源波动触发告警。告警升级告警发出后15分钟未认领自动升级到更高一级值班通道1小时未处理则电话通知。这套机制保证每条真实告警最终都会到达能决策的人手里而不是发出去就石沉大海。告警降噪机制上线后最直观的效果是单次故障产生的告警条数从平均几十条降到了两到三条而且条条都是能直接指导操作的信息。值班组的同学终于愿意把手机从免打扰里放出来了。注意告警降噪的目的不是减少告警而是把告警信息收敛到人脑能处理的粒度。如果为了减少告警而牺牲规则覆盖面那就本末倒置了。4. 可视化层从看到数字到看懂系统4.1 黄金指标与健康评分一屏看懂系统状态监控看板如果只是把一堆曲线堆在仪表盘上本质上还是看到数字不叫看懂系统。PLFM_RADAR在可视化层做了两件比较重要的事统一健康评分和服务拓扑。健康评分是给每个服务打一个0到100的分底层逻辑对应Google SRE体系里的黄金信号——请求量、错误率、延迟、饱和度。每个维度分配权重实时计算定期刷新。具体的评分逻辑做到规则引擎里每条健康评分策略会实时读取指定指标的最近五分钟窗口数据与基线值做对比得到基准分再根据错误率和饱和度做减分。实际配置中一个服务的评分大概是这样的计算方式服务: order-core 当前健康评分: 72 请求量健康度: healthy (当前454 req/s基线368 req/s上下浮动40%内) 错误率健康度: warning (当前3.1%基线1%超过基线指数) 延迟健康度: healthy (P99120ms基线200ms) 饱和度健康度: healthy (CPU 42%内存65%) 评分 100 - 错误率减分25 - 饱和度减分3 72整个系统看板的第一屏就是所有服务的健康评分列表按分数从低到高排序。分数低于80的标黄低于60的标红。值班同学接班后扫一眼第一屏就知道当前有没有需要立即处理的问题。这个一眼入状态的效果比盯几百张图表高效得多。4.2 服务拓扑与调用链可观测迅速圈定故障范围服务拓扑图是把雷达的扫描结果可视化的核心。PLFM_RADAR不依赖分布式追踪的采样数据来生成拓扑而是通过采集层上报的调用关系来构建视图。每个服务在启动时根据配置中心的服务发现注册自身信息Agent采集端通过监听服务间调用连接数来记录调用关系最终汇总成一个实时更新的调用拓扑。拓扑图上每个节点显示的是服务健康评分和请求量节点间的连线表示调用关系线宽对应流量大小。当某个服务故障时节点会从绿色逐渐变黄再变红与之相连的下游节点也同步显示状态的传播。这个图在故障定位时非常好用。有一次订单服务响应变慢从拓扑图上能直接看到流量从order-core指向inventory服务的那条线变粗了且inventory节点黄了问题范围几秒钟就圈定在inventory服务上不需要逐层翻日志排查。拓扑计算有个技术细节值得聊一下——调用关系的实时性问题。服务间调用的连接状态是高频变化的如果每次变化都全量重算拓扑计算量大且界面会抖动。我们的方案是维护一个有向加权图的增量快照调用信号到达时只更新对应边的权重和时间戳拓扑视图的刷新频率控制在10秒一次。这样既保证了实时性又避免了界面频闪。5. 部署落地与性能调优实录5.1 资源规划这套系统要吃多少机器很多做监控平台的团队死在监控系统本身资源消耗过大这个坎上。我见过一个团队上了全链路监控后监控资源占了业务资源的15%直接被叫停。PLFM_RADAR的资源规划是在设计阶段就算清楚了的。以我们当时的实际规模为参考150台物理节点约2000个业务实例每秒采集指标点约8万个每条数据平均大小约40字节。按这个规模做估算写入流量8万点/秒 × 40字节 3.2MB/s的原始写入流量加上监控本身的协议开销Kafka入口流量约5MB/s。这个量级用3个Kafka节点8C16G绰绰有余。存储容量原始数据7天8万点/秒 × 86400秒 × 7天 × 3倍压缩系数 ≈ 45GB左右。实际上VictoriaMetrics的压缩比Prometheus还高我们最终分配的SSD存储是120GB还有富余。查询性能核心查询场景是最近5分钟到最近24小时加上聚合降采样索引3节点的VictoriaMetrics足以保证100ms以内的P99查询延迟。整套系统的部署拓扑比较清晰Kafka三节点、VictoriaMetrics三节点、规则引擎服务双活部署在Kubernetes上、可视化层使用现有的Grafana。总共只比之前的Prometheus方案多占了四台虚拟机对业务资源的影响可以忽略。注意监控系统的资源规划一定要在上线前算清楚并留出至少30%的Buffer。监控系统是业务越好流量越大监控压力也越大的跟随型负载不能按平日规格卡死上限。5.2 写入链路与查询性能的调优实践性能调优是整个项目里最磨人的阶段。上线初期主要问题是写入路径上的瓶颈高峰期Kafka消费端Lag涨得非常快VictoriaMetrics写入经常超时。排查发现有两处设计缺陷。第一处是采集Agent的批量写入没有做时间维度的聚合。业务高峰时同一个服务在同一秒会产生大量只有维度标签不同的指标点如果不做聚合一个批量请求里可能包含上千条几乎一样的数据。优化方案是在Agent端加了一层预聚合按实体加核心维度的维度做缓冲5秒内合并同一维度的指标点再上报写入量直接减少了约70%。第二处是VictoriaMetrics的索引热度不均。高频写入的热门标签比如服务名集中在部分分片导致个别节点写入压力远高于其它节点。调整方案是把标签按基数级别分区高基数的标签单独分片低基数标签正常分片。这样调整后集群写入压力的分布均匀了很多。查询端的调优相对简单主要就是两个方面。第一是查询Grafana看板时的超时设置与聚合下推。能聚合的查询尽量下推到存储层完成前端只负责展示聚合结果避免一次拉几十万条原始数据到前端再聚合。第二是筛选条件前置化查询语句里先把不相关的时间范围过滤掉再执行聚合计算。这两项优化让P99查询延迟从原来的500ms降到了100ms以内。6. 常见问题排查与避坑指南6.1 监控平台自身故障速查表PLFM_RADAR运行了大半年各种问题也踩了不少。下面这张表是团队成员踩坑之后共同整理出来的速查表对维护同类系统的团队应该有些参考价值。常见问题可能原因排查办法与解决措施告警风暴大量规则同时触发上游依赖故障引起级联报错规则缺少分组聚合和抑制配置检查告警聚合策略是否生效为核心依赖服务增加抑制规则确认规则是否存在重复覆盖指标长时间断点后又突然恢复采集Agent内存溢出被系统杀掉Kafka分区堆积后时间戳乱序查看Agent内存占用和GC日志为Agent设置内存上限自动重启恢复在消费端按时间戳排序缓冲写入告警规则配置了却不触发规则表达式语法错误动态基线样本量不足静默窗口未关闭用规则回放功能检测表达式查看基线样本覆盖率检查静默窗口时段配置看板图表出现毛刺或跳变降采样聚合逻辑有误部分指标值未归一化对比原始数据与聚合数据曲线检查聚合函数与周期配置如5分钟聚合需要对齐到分钟边界存储磁盘写入增长过快指标基数爆炸某个维度标签值过多从写入流量统计中定位高基数标签设置基数限制并将高基数标签降级到上下文载荷6.2 实战心得监控规则需要持续运营最后说一点项目运营层面的体会。监控系统不是一个搭完上线就完事的项目它需要持续运营。告警规则要随业务变化持续调整每逢大促或者新版本上线健康评分和告警阈值都可能需要临时调整。PLFM_RADAR上线初期我们每周都会安排一次规则复盘会把本周触发的所有告警过一遍误报的调整规则漏报的补充规则新的业务场景添加规则。坚持了三个月之后告警准确率从最初的不到60%提高到了95%以上。另外强烈建议做一套规则回放工具。就是拿过去某段时间的真实数据当作输入重新跑一遍当前的规则集看会触发多少条告警。这套工具让我们在调整规则时不再盲改——先回放确认不会误报再发布规则。在业务高流量发生之前用历史数据预演能躲开不少线上故障。做PLFM_RADAR这大半年我个人最大的体会是监控系统做得好不好从来不取决于用了多少高大上的组件而取决于对业务的理解深度。规则引擎、降噪机制、拓扑视图这些都是手段核心是把什么算正常、什么算异常、异常了要怎么办这三件事想清楚。比如动态基线如果对业务没有足够的理解连按星期几小时建立分布区间这个思路都想不到更别提怎么设计了。监控和告警的本质是让系统在异常发生的时候有条理地告诉值班的人哪里出了问题、怎么找到根因、该怎么处理这套有条理的能力就是雷达的价值所在。
阅读完成 · 觉得有帮助?
咨询建站