ARTICLE DETAIL

资讯详情

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

实时平台监控雷达:从需求拆解到落地全流程实践

实时平台监控雷达:从需求拆解到落地全流程实践 PLFM_RADAR这个名字我第一次在项目清单里看到的时候第一反应是——又一个内部平台代号。但真把需求捋完才发现这玩意儿其实一点都不虚它解决的是很多团队都有的一个隐性痛点平台建好了但没人知道它每分钟到底跑得怎么样。你有数据有接口有服务但业务方问一句“今天平台稳不稳”你只能打开三个不同的后台截图拼起来回话。PLFM_RADAR说白了就是把平台的关键运行指标、业务数据和异常状态实时汇总到一块“雷达屏幕”上从混沌中抓重点。这篇文章就围绕这个项目聊聊从需求拆解、技术选型到落地实现的完整过程直接给能抄作业的方案。1. 项目概述与需求拆解1.1 先搞清楚PLFM_RADAR到底要干嘛项目名拆开看PLFM是Platform的简写RADAR则是雷达的意思组合起来就是“平台雷达”。它的定位不是一个普通的数据大屏不是把数据库里几十个指标拉出来画几张折线图那么简单。真正的雷达核心在于扫描、发现、告警要在海量信号里识别出值得注意的目标。PLFM_RADAR项目的本质就是给一个复杂平台装上这套“扫描-发现-告警”机制。我在做需求调研的时候把目标平台里所有角色都问了一圈。运维关心的是服务存活、响应时间、错误率运营关心的是今日活跃、订单量、转化漏斗研发关心的是慢查询、队列积压、依赖服务的SLA管理层关心的则更直接——平台整体健康度能不能用一个数字表达。需求看似五花八门但归拢一下无非两类可用性指标就是服务能不能用业务指标就是业务跑得好不好。而PLFM_RADAR要做的是把这两类指标在一条时间线上统一观测做到“一屏总览异常必现”。这个项目的关键点在于“实时”二字。离线跑批的报表很多团队都有但PLFM_RADAR从设计之初就锁定了秒级延迟的目标。所有指标从产生到上屏延迟不超过五秒。这意味着技术架构上完全不能用“每天凌晨跑T1任务”的思路必须走实时的数据管道。1.2 核心用户与核心场景锁定做这类监控平台最忌讳的就是大而全一上来想把所有指标都接进来最后往往做成一堆数字的陈列馆没人看。PLFM_RADAR在设计时定了三个核心场景所有开发资源优先为这三个场景服务第一个场景是值班盯屏。运维和研发在重点保障期例如大促、新版本发布需要紧盯屏幕一旦指标异常能立刻收到告警并且能快速定位到具体模块。这个场景要求“总览-下钻”的交互设计首页能看到全局健康分点进去能一路追到具体接口或者服务器节点。第二个场景是事后复盘。出了故障或者活动结束后团队需要快速回答“什么时候开始异常、影响范围多大、哪个环节先出的问题”。这就要求RADAR系统必须保留完整的时序数据并且支持按时间轴拖拽回放不能只剩一个当前状态的快照。第三个场景是业务感知。运营和市场团队不关心技术指标他们想知道活动的实时效果。所以PLFM_RADAR不仅要有CPU、内存这些技术指标还要有实时订单量、用户在线数、页面点击热力这样的业务指标并且两类指标能放在同一个时间维度里对比分析。这三个场景确认下来项目的边界就清晰了。技术指标聚焦在最核心的基础设施和应用性能业务指标聚焦在实时交易链路和用户行为。非核心的指标就算接进来也优先排到低优队列绝不抢占关键链路的计算资源。2. 技术方案选型与架构设计思路2.1 数据采集层的取舍PLFM_RADAR的采集对象五花八门。有MySQL和PostgreSQL里的业务数据有Nginx的访问日志有微服务框架暴露的性能指标还有云平台自带的监控API。如果每种数据源都单独写一套采集逻辑开发和维护成本会直接失控。这里我的选择是分而治之。基础设施层的指标直接用Prometheus生态node_exporter采集服务器资源JMX Exporter采集JVM指标Custom Exporter把业务埋点数据暴露成Prometheus格式。这套方案在云原生时代几乎是事实标准生态成熟各种Exporter即插即用。而业务数据这块走的是日志收集路线。服务的访问日志和业务操作日志统一通过Filebeat采集汇聚到Kafka。之所以不直接用Agent连数据库一是避免对生产库造成额外压力二是日志里能提取到比数据库表更丰富的信息比如用户行为路径、接口耗时分布。顺便说一句很多团队觉得采集层无关紧要随便写个脚本就上了等到后期要增加数据源的时候才发现没法扩展。PLFM_RADAR在采集层定义了一套统一的数据模型所有采集器最终都输出成标准的metric和event两种格式后面接任何新的数据源只是多写一个适配器的问题。2.2 实时计算引擎选型Kafka Streams还是Flink数据进到Kafka之后接下来要面对的是实时计算这一层。这里可选的方案不少Spark Streaming、Flink、Kafka Streams、甚至ClickHouse本身的物化视图都有人用。PLFM_RADAR选型时重点比较了Flink和Kafka Streams。Kafka Streams的优点是轻量嵌入式运行在业务服务里没有额外的集群需要运维适合做简单的状态聚合。但它的问题也很明显对流批一体和复杂事件处理的支持比较弱。PLFM_RADAR不止要做简单的计数还要做窗口内的去重统计、多流关联例如把订单流和支付流关联起来算支付成功率、以及基于时间序列的异常检测。这些场景用Flink的ProcessFunction和CEP库要方便得多。而且Flink的checkpoint机制在故障恢复时能做到Exactly-Once语义。注意监控场景下丢失几条数据表面上问题不大但如果丢的是故障产生的那几秒高延迟数据那恰好就是最关键的信号。所以我最终确定用Flink作为实时计算引擎部署在独立的Flink集群上通过YARN Session模式跑作业。消费Kafka里的原始数据流产出聚合后的指标流再写回Kafka的另一个Topic供下游存储和告警引擎消费。整个链路如下所示采集端Exporter/Filebeat→ Kafka原始Topic → Flink实时清洗聚合 → Kafka指标Topic → 下游存储/告警/可视化。2.3 存储选型为什么是ClickHouse而非ES实时计算产出的指标数据要面临的两个核心存储需求一是高吞吐写入峰值每秒可能要写数万条指标点二是快速聚合查询用户从总览页下钻到明细查询响应不能超过三秒。很多团队第一反应是用Elasticsearch毕竟日志场景用得熟但PLFM_RADAR实测下来ClickHouse在这类时序分析场景的优势非常明显。ClickHouse是列式存储对于这种“按时间范围扫描大量行但只取少数列”的分析查询磁盘扫描量和IO开销远远小于ES的倒排索引方案。更重要的是ClickHouse的聚合性能极强GROUP BY多个维度加时间窗口的查询在几亿条数据里能做到亚秒级返回。PLFM_RADAR将明细数据按天分区使用ReplicatedMergeTree表引擎配合一个专门为指标查询设计的物化视图把常用的分钟级、小时级聚合结果提前算好查询性能非常稳定。Redis在整套架构里的角色也不容忽视。它承担两件事一是保存告警规则的配置和状态每条规则是否处于触发、恢复、静默状态都存在Redis里二是承担实时排行榜和最新值缓存首页大屏上的“当前在线人数 TOP5 页面”这类查询直接走Redis不回ClickHouse保证大屏刷新不拖底。3. 核心模块详细设计与关键参数3.1 雷达健康评分模型PLFM_RADAR最亮眼的模块是全局健康度评分。这是给管理层看的“平台驾驶舱”里的核心数字。但这个分数怎么算特别容易拍脑袋。我见过不少项目把几十个指标加起来求个平均分结果看起来没什么毛病实际上毫无意义——某个核心服务挂了分数还在90以上因为被一堆不那么重要的指标稀释了。PLFM_RADAR采用加权层次评分法。指标分三层底层是原始指标中间层是领域评分基础设施、应用性能、业务增长、用户体验顶层是综合健康分。每层权重通过历史故障数据反推——把过去一年每一次P0/P1事故翻出来看哪些指标在事故前最先异常这些指标的权重就要上调。这比拍脑袋科学得多。每个底层指标会先做归一化处理。例如接口响应时间P99这个指标设定基线是200ms那么当前值除以基线得到一个比值再通过一个缓和函数映射到0到100的得分。这样设计的好处是得分在基线附近波动时变化不太剧烈但一旦超过阈值得分会快速下降从视觉和数字上同时给值班人员明确信号。实际执行下来这套健康评分模型在大小故障上的敏感度都不错算是整个项目中投入产出比最高的一个模块。3.2 实时告警引擎去噪全流程告警引擎是PLFM_RADAR的另一个核心模块也是在实施时最需要耐心调优的地方。告警引擎本身的逻辑并不复杂每隔十秒消费一次指标数据逐条匹配规则判断当前值是否触发阈值如果触发且持续时间达到条件就发出告警。难点在于去噪——监控系统告警太多跟没有告警一样糟值班人员习惯了狼来了真正的问题反而没人响应。PLFM_RADAR做了三重去噪。第一重是持续时间策略。指标连续异常三分钟才触发告警瞬时抖动只记录不打扰。第二重是告警聚合。同一台机器上的多个指标同时异常合并成一条告警按影响范围排优先级而不是刷屏发十条。第三重是智能静默。系统在识别到某个上游服务已经处于故障状态时会自动抑制下游服务的告警因为根因已经定位了下游异常只是连锁反应不需要重复打扰。告警渠道也是分级的。P0级核心业务受损同时走电话、短信、工作群机器人三条通道P1级走短信加群机器人P2级只在工作群推送。这样设计是为了让不同严重级别的问题用不同力度的方式触达正确的人避免所有告警都走最高级别的通道时间长了团队就麻木了。3.3 可视化大屏的布局与交互逻辑可视化大屏是PLFM_RADAR的门面也是很多领导和合作方第一眼看到的东西。但大屏最容易踩的坑就是为了炫酷而牺牲信息密度。PLFM_RADAR的大屏没有用太多花哨的3D效果核心设计遵循“一屏三层”的信息架构。最上层是全局状态栏显示综合健康分、核心业务实时吞吐、异常事件滚动列表颜色用红黄绿三色标识状态。中间层是趋势分析区展示关键指标的24小时曲线这里特别做了异常标定——如果某段时间指标异常曲线背景会有一个浅红色的透明标记块值班人员一眼就能定位异常窗口。最下层是下钻面板点击某个节点或者服务下方立即展示该模块的明细指标和依赖关系。这个大屏还有一个特别实用的“时间旅行”功能。输入一个历史时间点整个大屏的数据状态会回放到那个时刻配合故障复盘使用效果极佳。原本需要翻日志对着时间线推测的流程现在直接可视化看板回放团队对故障发生过程的理解效率提升了一个量级。4. 实操过程与关键环节的实现细节4.1 环境准备与部署踩坑记录PLFM_RADAR整套系统涉及的组件不少服务器规划我建议至少准备七台机器。三台跑Kafka和Flink集群两台跑ClickHouse集群一台跑应用服务和可视化后端一台跑Prometheus和AlertManager。如果有条件开发和测试环境各一套生产环境另算。下面是我当时搭建环境时整理的版本清单全部是实际验证过的组合操作系统CentOS 7.9内核3.10Kafka2.8.0三节点每个节点磁盘独立挂载Flink1.13.2YARN Session模式ClickHouse21.8.4.51两分片一副本配置Prometheus2.30.3可视化Grafana 8.2 自研Node.js后端部署采坑方面有几点值得拎出来说。Kafka的堆内存和页缓存配置不当会导致频繁Full GC实测下来Kafka的堆内存控制在4G左右剩余内存留给操作系统页缓存吞吐表现最理想。ClickHouse的max_threads参数默认值在当前机器上容易把小查询拖慢我建表后把它调低了一半查询响应反而更快了——因为避免了线程过多导致的上下文切换开销。最关键的一个坑是时区问题。Flink默认使用服务器本地时区而ClickHouse的DateTime类型不带时区信息两边如果设置不一致时间窗口聚合出来的数据会整体偏移八个小时而且这种错位在可视化曲线上很难一眼看出来得花不少时间排查。后来统一规定所有组件全部使用UTC时间存储只在可视化展示层转换为北京时间这个坑才算彻底填掉。4.2 Flink实时计算作业的关键实现Flink作业的核心逻辑是从Kafka原始Topic消费数据做ETL清洗然后按窗口聚合指标输出到Kafka指标Topic。下面我给出一个关键片段展示PLFM_RADAR里最典型的窗口聚合逻辑DataStreamMetricEvent metricStream env .addSource(new FlinkKafkaConsumer( raw_metrics_topic, new MetricEventDeserializationSchema(), kafkaProps)) .assignTimestampsAndWatermarks( WatermarkStrategy .MetricEventforBoundedOutOfOrderness(Duration.ofSeconds(10)) .withTimestampAssigner((event, ts) - event.getTimestamp())) .filter(event - event.getMetricValue() 0); DataStreamMetricAggregate aggregated metricStream .keyBy(MetricEvent::getMetricKey) .window(TumblingEventTimeWindows.of(Time.seconds(30))) .aggregate(new MetricAggregateFunction()) .filter(agg - agg.getCount() 0);这里有两个细节值得重点说。第一是Watermark策略我用的是允许十秒乱序的BoundedOutOfOrderness因为实测数据从采集端到Flink的传输链路在高峰期确实会有几秒的抖动设置十秒的容忍窗口可以在不显著增加延迟的前提下避免大量数据因为乱序被丢弃。第二是TumblingEventTimeWindows的滑动窗口用30秒窗口。这个粒度既能捕捉到分钟级以下的异常抖动又不会因为窗口太小导致噪声太多。告警判定逻辑也在Flink里做了一部分预聚合。Flink作业直接输出每分钟的指标平均值、最大值、P95值到Kafka减少告警引擎的重复计算压力。4.3 ClickHouse表结构设计要点ClickHouse的表结构设计决定了后续所有查询的性能。PLFM_RADAR的指标明细表用的是ReplicatedMergeTree引擎按天分区下面是核心建表语句中的关键部分CREATE TABLE radar.metrics_daily ( event_time DateTime CODEC(Gorilla, ZSTD), metric_key String CODEC(ZSTD), metric_value Float64 CODEC(Gorilla), dimension_tags String CODEC(ZSTD), host_ip String CODEC(ZSTD), service_name String CODEC(ZSTD) ) ENGINE ReplicatedMergeTree(/clickhouse/tables/{shard}/metrics_daily, {replica}) PARTITION BY toYYYYMMDD(event_time) ORDER BY (metric_key, event_time) TTL toDateTime(event_time) INTERVAL 30 DAY;可以看出排序键是(metric_key, event_time)这是为“按指标查询时间范围”这个最常用的查询模式设计的。如果按服务名排序查询单个服务所有指标时会更快但按指标名查询的频次高得多当前的设计是实测对比后的最优解。TTL设置了30天自动清理控制存储成本同时保留足够的复盘窗口。数据写入方面强烈建议用ClickHouse的批量写入接口每批至少攒够5000条或1秒的数据再写入。单条insert在小数据量场景无所谓在写入高峰时会导致merge压力过大甚至可能撑爆内存。PLFM_RADAR实测用Java的ClickHouse JDBC驱动配合批量写入写入吞吐比逐条插入提升了好几倍。4.4 告警规则配置与阈值设定实例告警规则阈值怎么定是一个很靠经验的事情。定得太松真正出问题的时候发现告警没触发定得太紧告警风暴来了没人看。PLFM_RADAR采用“基线动态静态兜底”的双轨策略。静态兜底规则是基础防线例如CPU使用率大于90%持续5分钟接口错误率大于5%持续3分钟这类规则跟业务波动无关任何时候都应该触发。动态基线规则则聪明一些系统自动计算过去14天同一时刻指标的历史分位数例如取P95作为参考值当前指标超过历史P95的1.5倍就判定为异常。举个例子某个普通工作日早上10点的订单量可能在1000左右但如果双11大促期间也是1000按静态规则可能就告警了——实际上业务可能还增长了呢。用动态基线就不会误报。不过动态基线需要积累足够的历史数据才有参考意义上线初期建议先用静态兜底规则扛住跑了两周之后再逐步放开动态规则。下面给一个实际使用的告警规则示例rules: - rule_name: 核心接口P99响应时间突增 metric_key: http_server_requests_p99 condition: operator: above_dynamic_baseline threshold_ratio: 1.5 baseline_percentile: 95 duration: 180s severity: P1 channels: [sms, work_wechat]4.5 大屏后端接口性能优化笔记可视化大屏的接口性能直接影响使用者对整套系统的第一印象。大屏上所有图表接口要求1秒内返回超过这个阈值前端轮询就会堆积请求造成雪球效应。PLFM_RADAR在大屏后端做了几层优化才达到这个标准。第一层是缓存。除实时大盘数据外所有历史趋势图的查询结果缓存到Redis缓存时间跟图表的时间粒度挂钩。分钟级数据缓存30秒小时级数据缓存5分钟。这样ClickHouse的查询压力能下降不少大屏在多人同时打开时不会互相拖垮。第二层是预聚合。ClickHouse的物化视图把原始数据按分钟、小时、天三个粒度分别预聚合图表查询时优先命中预聚合结果只有需要下钻到明细时才查询明细表。这里有个细节要留意物化视图在数据插入时同步更新所以查询性能虽然快了但数据写入的CPU开销会上升需要监控ClickHouse的写入延迟如果偏高就要考虑降低物化视图的粒度或者扩展节点。第三层是接口精简。大屏页面每次轮询请求一批数据但并不是所有图表都需要全量刷新把接口按“秒级更新”和“分钟级更新”拆成两组前端分别按不同频率请求后端负载会平滑很多。5. 高频故障与排查实录5.1 数据延迟毛刺的生产事故PLFM_RADAR上线一个月后遇到了第一次比较严重的数据延迟事故。大屏上所有指标都出现了约两分钟的停滞之后突然涌现了大量“旧数据”。最开始以为是Flink任务挂了检查之后发现作业还在运行但消费延迟的监控显示Kafka Lag在一路狂飙。顺着链路排查发现瓶颈在采集端。那两天恰好上游服务发版日志量比平时翻了几倍Filebeat的日志采集吞吐跟不上导致数据在采集端就产生了积压。Flink这边消费能力没问题但数据进来是乱的所有窗口的计算都被等待进水时间拖慢了反映到大屏上就是数据停滞。这个故障给了一个很重要的教训端到端的链路瓶颈不一定在计算环节很多时候是默默无闻的采集端先扛不住。后来我们在采集端加了双倍的Filebeat实例并且给采集端单独做了水位线监控——只要采集端积压超过30秒立刻告警把问题消灭在源头。5.2 告警风暴引发的值班疲劳处置项目运行第二个月的时候告警风暴开始成为最让人头疼的问题。那段时间正好赶上一批依赖的第三方服务接口升级整个下午告警消息几乎没停过值班同事干脆把群消息静音了。这样做的后果可想而知某个核心服务真的出故障时因为消息被淹没在大量无关告警里响应时间反而比平时更长。后来我们做了两个关键改进。第一个改进是加入依赖拓扑感知。在系统里维护了一张服务依赖图告警产生时先判断当前告警节点的上游是否有已触发的告警。如果有当前告警自动降级为“关联告警”不做独立的变更响应。这个改动减少了大量下游连带告警。第二个改进是告警轮询升级机制。一条告警触发后如果10分钟没有得到确认会再次推送并升级到下一个值班人确保告警不因为静默而石沉大海。5.3 数据断点场景下的前端体验优化还有一个高频问题是数据断点对可视化体验的影响。在实际运行中总会有某个瞬时的数据没采集到或者因网络问题丢失比如数据库连接闪断导致某几条写入失败。这种情况下前端图表上出现凹坑或断线业务方问起来很多时候只是数据丢失并非业务真的出现波动。问题的核心在于这种情况很难用程序自动判断是“数据真没产生”还是“数据采集丢失”。PLFM_RADAR的做法是双管齐下。一方面在采集端做补偿机制Flink作业增加了一个15分钟的延迟数据处理窗口晚到的数据可以自动补进来弥补大部分偶发丢失。另一方面在可视化前端做了数据可信度标记如果某个时间点的数据覆盖率为0图表上不会硬画一条连线而是渲染为空心点并置灰鼠标悬停时会提示“该时段数据缺失”。这就把数据可信度的问题透明化避免业务方误读图表。再补充一个前端细节。大屏采用的WebSocket推送正常情况下新数据到达后秒级更新延迟很小。如果检测到WebSocket连接断开前端会自动切换为HTTP轮询兜底并且显示一个小黄点提示当前处于降级模式。这个设计在弱网环境下很实用毕竟大屏有时候要放在前台展示WiFi说不准什么时候就抖一下。6. 落地经验与后续演进思考6.1 监控项目推进过程中的组织协作要点做PLFM_RADAR这类项目技术只是其中一小半工作另外一大半是跟人打交道。各团队对于“被监控”这件事天然有一种防御心理——研发团队担心指标不好看被领导点名运维团队担心告警太多活儿变多业务团队担心数据口径对不上要反复解释。我的经验是一定要提前对齐口径。在项目启动阶段就成立一个数据口径专项小组把每个核心指标的定义、统计逻辑、展示方式跟各方确认清楚特别是业务指标一定以业务方的口径为准。技术指标如果有歧义也要在文档里写清楚。DSL规范定了后面就能减少很多扯皮。另一个关键动作是分阶段灰度。PLFM_RADAR上线时没有一步到位接全所有指标而是先接了基础设施和两个核心业务的指标跑了两周把告警阈值、可视化效果都调稳了再逐步扩展到其他模块。这样既给了团队适应时间也为后续调优积累了基线数据。6.2 后续可以扩展的方向和我的个人体会PLFM_RADAR目前已经平稳运行了一段时间但在实际使用中我也总在想这套系统还有哪些可以做得更好的地方。最想扩展的是智能异常检测。目前基于动态基线的告警规则已经能挡掉大部分误报但对于比较复杂的非线性异常模式例如两个指标之间相关性突然断裂仍然不太敏感。后续想尝试引入时序异常检测算法用历史数据训练模型让系统能自动发现值班人员还没意识到的潜在问题。另一个想完善的是根因分析能力。现在出了故障系统能快速呈现现象但定位根因还是要靠人工看依赖图和数据链路。如果能把全链路追踪数据和指标数据打通故障时自动生成“疑似根因链”值班效率还能再上一个台阶。虽然这块还在探索但我个人觉得是值得投入的方向。最后说点实在的。整个项目做下来我最深的体会是监控系统本身也是一种“业务系统”它同样需要关心用户体验、关注数据准确性和追求极致的可靠性。技术选型只是起点真正决定这个雷达能不能发挥作用的关键还是在细节里。告警阈值合不合理、大屏看得顺不顺眼、数据有没有口径问题——这些不起眼的小事才决定了一个监控项目最终是被高频使用还是被关进后台某个角落里吃灰。我建议所有想搭类似系统的团队动工之前先花足够的时间把需求场景和指标口径聊透技术反而是最不着急的部分。方向对了后面的路自然顺畅。
返回列表