ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

PLFM_RADAR:跨平台统一监控与告警收敛系统实践

PLFM_RADAR:跨平台统一监控与告警收敛系统实践 1. 为什么我会做一个叫PLFM_RADAR的项目事情得从去年接手的那套全家桶监控说起。当时部门里跑着六七个业务平台每个平台都有自己的告警渠道有的往群里丢消息有的发邮件还有一个特别老的系统只能靠人每天定时去刷页面。白天还好一到夜里告警声此起彼伏值班同事经常被折腾得够呛更离谱的是同一台数据库服务器磁盘快满了三个平台各报各的就是没人第一时间去处理。那段时间我反复想一个问题——我们缺的不是监控工具而是一个能把所有平台的运行状态拉通、统一研判、统一告警的雷达。PLFM_RADAR这个项目就是在这个背景下立项的。名字拆开看PLFM取Platform之意RADAR则点明了这套系统的核心像雷达一样持续扫描各个平台的健康信号捕捉异常目标提前发出预警。这个项目的定位很明确不去重复造轮子做数据采集而是做一层统一的中枢层把散落在各个平台里的指标、日志、事件汇聚到一起用一套统一的规则引擎做交叉分析和告警收敛。它适合谁参考如果你所在团队的监控体系同样是平台多、工具杂、告警乱的状态或者你正准备搭建一套自己的统一观测系统这篇文章里的设计思路、踩坑记录和调优参数应该都能直接派上用场。下面我把PLFM_RADAR的整体设计、核心模块、部署要点和实际运行中遇到的坑完整地梳理一遍。2. 立项前的三个核心判断决定PLFM_RADAR技术路线的依据系统设计最怕一上来就堆技术栈。我在动手之前花了差不多一周时间做调研和取舍有几个关键判断直接影响后续架构走向值得先展开说说。2.1 选型判断一采集层不做代理优先走API接入第一个争论点就是要不要在每个平台服务器上装Agent采集器支持Agent方案的人理由很充分——数据精度高、可采集指标维度全、不受目标系统接口限制。反对的声音也很直接六个平台分布在不同的网络分区一半是第三方厂商的系统厂商根本不会允许你往生产服务器上随便装Agent。最终我选择了API接入为主、被动接收为辅的路线。第三方平台基本都会提供REST API或者数据库只读账号通过接口拉取指标数据和告警事件既不侵入业务系统也不影响目标平台的性能。自主可控的平台则可以配置消息队列或Webhook把事件主动推给PLFM_RADAR。这个决策带来的好处在后期非常明显整个雷达系统的部署完全独立不依赖业务平台的任何变更上线时没有协调过一份变更单。补充一点实践经验如果遇到某些老旧平台连API都没有只有数据库可以申请只读账号直连采集。但务必严格控制只读权限而且查询频率要克制我就见过有人每5秒查一次告警表直接把源库的慢查询日志刷了整整一屏。2.2 选型判断二告警引擎必须支持多源关联而不是单点阈值传统监控的告警模式大都是单指标阈值触发CPU使用率超过90%就告警接口错误率超过5%就告警。这套逻辑在平台少的时候够用但一旦平台数量上来了会产生两个严重问题一个是告警风暴同一个故障被多个平台重复上报另一个是上下文缺失单个指标异常根本看不出真正的根因。PLFM_RADAR的告警引擎在设计上把关联分析放到了核心位置。我要求规则引擎必须能同时消费多路数据源支持时间窗口内的跨平台事件匹配。比如当平台A的订单量骤降、平台B的支付接口超时率上升、平台C的数据库连接数打满这三条告警在同一个两分钟窗口内出现时系统应该自动聚合成一条交易链路整体异常的高优告警而不是分别弹三条互不相干的消息。这个判断直接决定了底层技术选型规则引擎需要支持流式处理、状态窗口和复杂事件匹配。我在对比了Drools、Esper和自己写状态机之后决定基于Flink的CEP库来自研一套轻量级关联引擎理由后面会详细说。2.3 选型判断三存储层必须区分热数据和冷数据这是最后一个关键取舍。一开始有人建议把所有原始数据都存进Elasticsearch统一检索方便。但算了一笔账之后发现行不通——六七个平台的指标数据加告警事件高峰期每秒入库几千条按原始粒度全量保留的话单月存储量就得奔着几个TB去成本完全失控。最终存储方案分成三层热数据最近7天保留原始指标和事件明细存放在ClickHouse用于实时查询和关联分析温数据7~30天按分钟粒度聚合后的指标数据同样放ClickHouse用于趋势分析和容量规划冷数据30天以上只保留告警事件和日统计摘要归档到对象存储满足审计需求即可。这样一套分级策略执行下来存储成本直接降到原来的五分之一不到而查询体验并没有明显下降。毕竟做监控的人心里都有数超过一周的原始曲线真正会去回看的频率极低聚合数据足够撑起绝大多数分析场景。3. PLFM_RADAR的系统架构与各模块实际职责整体架构定下来之后我按照接入-处理-存储-展示-告警五个环节来组织模块。每个模块的职责边界划得很清楚这也是后期维护省心的主要原因。3.1 接入层的双通道设计接入层是PLFM_RADAR的门面承担所有外部数据的入口职责。我采用了双通道设计分别对应主动拉取和被动接收两种模式。主动拉取通道我把它命名为Collector。它是一组定时任务调度的采集器按照配置的周期调用各平台的API接口。这里有一个很关键的抽象所有平台的采集逻辑统一封装成指标采集器和事件采集器两种接口新接入一个平台时只需要实现对应的接口注册到调度器里就行完全不用改动其他模块。目前接入了六个平台采集频率从30秒到5分钟不等总共跑了十几个采集任务。被动接收通道则是一个基于HTTP的Webhook服务和一个MQ消费者。第三方平台或者自研系统可以通过标准格式的消息推送告警事件或关键业务指标PLFM_RADAR收到后直接解析入库响应延迟控制在秒级。为了统一后续所有模块的处理逻辑我设计了一套内部数据规范所有数据进入处理层之前都会被转换成统一的JSON结构包含数据源标识、事件类型、时间戳、指标名、指标值、维度标签等字段。这一步至关重要因为如果各平台的数据格式不统一后面的关联分析逻辑会越写越复杂最后变成一团乱麻。3.2 处理层的规则引擎与关联分析处理层是整个系统的大脑。数据进来之后首先经过清洗和标准化——过滤掉明显异常的空值、格式错误、重复数据然后分流到两条截然不同的处理链路里。第一条链路是指标处理链路。流式数据经过窗口聚合按平台、按业务类型分维度计算均值、P95、最大值、最小值等统计值一方面用于实时展示另一方面写入温存储供后续分析用。第二条链路是事件处理链路也是PLFM_RADAR最有价值的部分。事件流进入Flink CEP引擎后会与预先配置好的告警规则进行匹配。我在规则设计上做了三个层级基础阈值规则单指标越过绝对阈值即触发例如平台A的登录接口成功率连续3分钟低于95%趋势变化规则指标在时间窗口内的变化幅度超过阈值即触发例如平台B的订单量在5分钟内下降超过30%跨源关联规则不同平台的事件在时间窗口内出现组合即触发例如平台A的请求量异常升高 平台B的数据库慢查询数增加 平台C的网关5xx增加同时出现时自动生成交易链路故障告警。这套三层规则看起来复杂实际落地时其实只需要在Flink CEP的Pattern定义里组合不同的条件即可。我维护了一个规则配置文件支持热加载调整规则不需要重启任务这对后续反复调优帮助极大。3.3 存储层的表结构设计与数据生命周期ClickHouse是我最终选定的主存储引擎主要是看中了它在聚合查询上的性能优势。我设计了四张核心表指标明细表、指标聚合表、事件明细表、告警记录表。指标明细表和事件明细表使用MergeTree引擎按时间戳排序分区键按天设置告警记录表增加了平台ID和规则ID作为索引字段方便快速检索。这里有个细节值得说一下ClickHouse的TTL功能我用来实现数据分级策略。表创建时可以指定TTL表达式比如指标明细表的TTL设为7天到期后自动删除聚合表TTL设为30天告警记录表TTL设为90天。归档到对象存储则是通过一个每晚跑批的脚本完成的流程很简单——读取前一天的数据写入Parquet文件上传对象存储然后从ClickHouse删除对应分区。这套流程跑了大半年稳得很。3.4 展示层与告警触达的设计思路展示层我没有选择自己从零开发大屏而是直接用了开源的Grafana通过ClickHouse数据源插件直连查询。Grafana的仪表盘能力完全够用而且社区里有大量现成的图表插件省去了前端开发的巨量工作。我为六个平台分别设计了总览面板、详情面板和拓扑面板最常用的是一张全局雷达总览大屏上面同时展示各平台的健康分、活跃告警数、核心接口的实时延迟和错误率。告警触达部分优先级从高到低设计了三种通道电话语音告警只用于最高优级的故障、短信通知、群机器人消息。通道的切换逻辑放在告警路由模块里根据告警级别和业务影响范围自动选择。这里最实用的一个设计是认领-升级-关闭的告警生命周期管理告警触发后先进入待认领状态如果15分钟没人认领会自动升级并通知上一级值班人员处理完成后需要填写处理记录才能关闭。这个机制极大减少了告警被忽略的情况。4. 部署落地的完整过程与关键参数调优架构设计是一回事真正部署上线又是另一回事。PLFM_RADAR从开发完成到稳定运行中间经历了三轮迭代调优。我把部署过程里最重要的部分拆出来讲。4.1 环境规划与组件部署顺序我当时用了三台物理机搭建这套系统配置都是16核64G内存操作系统是CentOS 7.9。整体组件清单如下组件数量用途资源占用Flink集群3节点流处理与CEP规则引擎每节点8G内存ClickHouse3节点指标与事件存储每节点16G内存Grafana1节点可视化展示2G内存足够告警路由服务1节点告警收敛与通道分发2G内存Redis3节点状态缓存与窗口去重每节点2G内存Nginx1节点反向代理与静态资源1G内存部署顺序上有讲究。我建议先把Redis和ClickHouse这样的基础组件拉起来因为它们没有复杂的依赖然后部署Flink集群因为它是核心计算引擎最后再上Grafana和告警服务。每个组件启动后先做自检比如ClickHouse要用clickhouse-client跑一条简单查询验证连通性Flink要检查TaskManager的注册情况确保没问题再进行下一步避免把问题混在一起排查。4.2 Flink CEP规则引擎的实际实现思路下面这段是PLFM_RADAR的核心代码逻辑我在自研CEP引擎时采用的方案是用Flink的CEP库定义模式通过DataStream API把多路数据流合并后送入模式匹配。以交易链路关联告警规则为例规则的Pattern定义大致如下Pattern.Eventbegin(platformA_anomaly) .where(new SimpleConditionEvent() { Override public boolean filter(Event event) { return event.getPlatform().equals(platformA) event.getMetric().equals(request_count) event.getValue() thresholdA; } }) .followedBy(platformB_anomaly) .where(new SimpleConditionEvent() { Override public boolean filter(Event event) { return event.getPlatform().equals(platformB) event.getMetric().equals(slow_query) event.getValue() thresholdB; } }) .followedBy(platformC_anomaly) .where(new SimpleConditionEvent() { Override public boolean filter(Event event) { return event.getPlatform().equals(platformC) event.getMetric().equals(gateway_5xx) event.getValue() thresholdC; } }) .within(Time.minutes(2));这段代码的含义很直观在2分钟的时间窗口内如果依次检测到平台A请求量异常、平台B慢查询增多、平台C网关5xx上升就认为发生了一次跨平台的交易链路故障告警。这个例子体现了雷达的核心思想——不是孤立地看每个点的异常而是看多个点之间的时空关联。实际部署时还踩了一个坑Flink CEP默认的情况下事件时间是处理时间而多个平台的数据源上报延迟各不相同最多能差出十几秒。如果不做水位线设置跨平台的事件窗口匹配就会频繁错过。解决方法是改为事件时间语义并按各平台的上报延迟分布设定水位线延迟我最终设置为30秒。4.3 告警收敛的去重与降噪参数告警收敛是PLFM_RADAR上线后让我投入精力最多的部分。第一版上线的时候告警风暴现象非常严重一晚上能弹出三四百条消息值班同事直接在群里投诉。后来我专门花了三天时间做收敛策略调优总结了三个关键参数第一个是窗口去重。相同平台、相同规则、相同对象的告警在10分钟窗口内只推送一条。这个逻辑用Redis的SETNX命令实现key由平台、规则、对象组成value是时间戳过期时间600秒每秒只执行一次压力可以忽略。第二个是依赖关系的告警抑制。我维护了一张依赖关系表记录各平台之间的上游下游依赖。比如平台C依赖平台B的接口如果平台B的接口故障告警已经触发那么在平台B恢复之前平台C相关的该接口调用异常告警自动抑制直接在告警记录里标注被依赖故障抑制。这个策略直接砍掉了大约60%的无效告警。第三个是业务低峰期的分级降噪。每天凌晨2点到6点业务低峰期自动将P2级别的告警延迟合并为日报推送不再实时打扰值班人员。只有P1和P0级别的紧急告警才会在深夜触达。这个措施不是为了降低告警灵敏度而是尊重人的注意力——凌晨的每一次无效打扰都会降低对真正严重告警的警觉。5. 从上线到稳定这段时期踩过的坑和完整排查链任何系统不踩几个坑都算不上真正落地。PLFM_RADAR上线后的头两个月我记录了大大小小十几个问题。这里挑四个最有代表性的把完整的排查过程写下来这比直接给结论有用得多。5.1 告警风暴规则上线当天值班同事差点炸毛现象很直接某天下午我上线了新版本加入了跨平台关联规则结果当晚8点开始群机器人消息基本没停过到11点累计弹了400多条。值班同事在群里发了一个字停。排查过程是这样的。我先导出了当天的告警记录按规则ID和平台维度做了聚合发现80%的告警都来自同一条新上线的规则——就是上面那段三平台关联的交易链路故障规则。我怀疑是规则本身的阈值设得太低导致触发太频繁。进一步查了各平台指标明细表发现那天的数据确实有一些波动但远没到达影响业务的级别。真正的问题出在规则逻辑上。Flink CEP的followedBy是严格顺序匹配但我当时并没有意识到由于三个平台的数据上报时间存在偏差CEP会把不同时间点的偶发抖动强行匹配成一条链路故障而且每个匹配都会独立触发告警。解决办法有两个一是把平台之间指标的相关系数计算加进去只有当三个指标的异常在时间分布上确实重合时才触发二是在告警生成前增加一个二次确认机制——命中规则后先查询各平台最近5分钟的原始指标做一次加权校验确认真实异常率超过设定指数才推送。我最终采用的是二次确认机制改动成本低效果立竿见影。上线当晚告警量直接从400条降到了20条以内。5.2 ClickHouse查询从秒级变成分钟级存储膨胀问题系统运行一个月后某天早上我发现Grafana上的Dashboard加载变得非常慢部分面板查询耗时从几百毫秒涨到了几分钟。明显是ClickHouse出了问题。我先查了磁盘使用率发现数据量增长远超预期。进一步排查发现指标的基数出了问题。采集器在记录指标时把请求参数中的用户ID和订单ID也塞进了标签维度导致每个请求都会产生一条独立的标签组合。比如一个平台的订单查询接口指标标签组合数量从几十个爆炸到几十万个。ClickHouse在聚合查询时需要对高基数标签做分组性能自然直线下降。修复方案很明确在采集器里增加了标签白名单机制只允许预先定义的业务标签平台ID、接口名、机房等进入指标写入用户ID和订单ID这类高基数标签一律排除如有需要可以放入单独的trace系统而不是监控系统。修复后重建了这一个月的聚合表查询性能恢复到了毫秒级。这件事给我的教训很深刻监控系统的维度设计必须在源头控制指标基数爆炸的治理代价远大于事后的任何优化。5.3 告警延迟增大到两分钟Flink背压排查实录有段时间群里的告警消息总比实际情况慢两分钟以上。告警这玩意儿延迟久了就失去了实时监控的意义。我开始排查Flink任务的运行状态。打开Flink的Web UI看到指标处理链路的算子背压指标已经是红色高亮状态说明处理速度跟不上数据流入速度。CPU和内存占用倒是正常问题应该出在算子的计算逻辑上。进一步对链路上的算子做耗时分析发现是规则匹配算子里有一段调用了外部Redis做二次校验的代码每次匹配都要做两次网络请求在高吞吐场景下产生了大量等待。优化方案有两个方向一是把Redis校验逻辑改成异步IO二是做成批量校验。异步IO是Flink的原生能力改造起来最方便。我使用Flink的AsyncFunction重写了那段逻辑把串行网络请求变成了并发请求。改完后背压指标回落到正常告警延迟降到了5秒以内效果显著。5.4 多平台时间不同步导致的关联误判这个坑是最隐蔽的。有段时间跨平台关联规则总在凌晨出现偶发误报时间毫无规律让人无从下手。后来在一次排查中我随手对比了同一个故障在三个平台里的时间戳发现平台B的事件时间比另外两个平台整整晚了47秒。根源找到了平台B所在机房的一台NTP服务器同步配置错误导致该平台的所有日志和事件时间戳都有偏差。而我的CEP规则使用了事件时间语义后时间偏差直接影响了跨平台事件的窗口匹配——明明是同一时刻发生的问题看起来却像在不同时间发生CEP自然匹配不上。解决方案是双管齐下。短期方案在接入层的标准化处理中加入时间偏移校准配置每个平台可以单独配置时间偏移量在数据进入处理链路前自动修正。长期方案推动平台B的运维修复NTP同步。这件事让我意识到做跨平台关联分析时时间基准的统一和校准不是可选项而是必选项。6. 性能测试与资源评估这套系统到底能扛多大压力PLFM_RADAR正式推向生产环境前我做了一轮完整的压测。压测的目的不是为了证明系统有多强而是确认在极端情况下的表现提前找到短板。6.1 各环节的压测数据我用一台单独的压测机器模拟多平台数据源分别测试了接入层、处理层和存储层的极限吞吐。接入层的测试结果Collector同时运行20个采集任务使用8个并发线程时API拉取吞吐稳定在每秒8000条事件Webhook接收端的极限在每秒2万条请求超过这个量Nginx的worker连接数会打满表现为请求排队。处理层的测试结果Flink集群处理标准格式事件的极限吞吐约为每秒3万条规则匹配延迟平均100毫秒。背压出现的临界点大约在每秒4万条超过这个值算子开始积压再往上就需要扩容TaskManager。存储层的测试结果ClickHouse的写入性能远远不是瓶颈单节点每秒可写入10万行以上真正需要注意的是查询。高基数标签查询和跨多表关联查询最优全表扫描的聚合查询则明显慢。综合来看PLFM_RADAR的瓶颈首先出现在接入层其次是Flink处理层。当前六平台的生产负载大约只有系统极限能力的15%余量充足即便未来平台数量翻一倍现有资源也够用。6.2 根据压测结果做的三项容量调整压测完我做了三项调整都是为了提升系统的工程健壮性。第一项是接入层的限流熔断机制。我在Webhook入口处增加了一层基于令牌桶的限流器当请求速率超过设定的每秒1.5万条时直接丢弃超限请求并记录错误日志同时返回429状态码。目的在于防止某个平台异常突发写入时把整个雷达系统拖垮。第二项是为Flink的Checkpoint配置了增量检查点。状态数据定期持久化任务重启时可以快速恢复。我设置了每5分钟做一次增量Checkpoint存储到HDFS。实际测试中一个节点宕机后的恢复时间控制在1分钟以内对告警链路的影响可接受。第三项是Grafana面板的查询缓存。把常用面板的查询结果设置为60秒缓存显著降低了ClickHouse的查询压力。大屏模式的刷新间隔也调整到了15秒一次不再追求每秒级别的更新因为监控场景下15秒的数据延迟完全可以接受。7. 这个项目的边界、后续演进方向和个人总结PLFM_RADAR到目前为止已经稳定运行了半年多。这半年的实际效果如何我拉了一组数据告警总量从最初每天500多条降到现在每天40条左右其中真正需要人工处理的平均每天5条跨平台故障的平均发现时间从过去的15分钟以上压缩到了3分钟以内最直观的是值班同事的反馈——晚上终于能睡个整觉了。当然这套系统的边界也很清晰。它目前做得更多是观测和收敛在故障自愈方面还比较薄弱。比如检测到某个平台的磁盘使用率超过阈值后系统只能通知人去处理还做不到自动触发清理流程。另一个方向是根因分析智能化现在的跨平台关联规则还依赖于人工经验配置未来可以考虑引入一些异常检测算法让系统自己从历史告警数据中学习关联模式。这两块是我计划在PLFM_RADAR二期迭代中重点投入的方向。最后分享一点个人体会。做这类系统最容易犯的错是一开始就追求功能大而全。我早期规划里甚至有自动生成周报、容量预测这些功能后来全部砍掉了。现在看来砍得对——PLFM_RADAR能顺利落地并被团队接受恰恰是因为它把统一接入、关联分析、告警收敛这三件事做透了其他都是锦上添花。监控系统的价值永远在于能让人少操心而不是制造更多需要操心的东西。如果读者你也正在搭类似的项目我的建议是一样的先把这三件事做扎实再想别的。
返回列表