3. 告警监控系统架构设计归纳总结

做 CRL 大小突变告警,架构设计是根基。你可能觉得不就是看个 CRL 文件大小变化吗?没那么简单。我当年刚接手时,也以为搭个定时脚本就完事了。结果第一次线上突变,告警延迟了 8 分钟——嗯,原因就出在架构太"朴素"。

今天我把这几年打磨出来的一套架构方案拆开讲。你会发现,它不光能防 CRL 突变,换其他指标也一样好用。

3.1 架构核心思路:分层解耦

别让所有逻辑挤在一个进程里。我习惯把系统拆成四层:采集层、处理层、存储层、展示与处置层。每层只干一件事,出了问题也好排查。

分层 职责 常见组件 我踩过的坑
采集层 从 CDN / 证书源站拉取 CRL 文件,记录大小、时间 定时任务、Agent、HTTP 客户端 并发拉取没做限流,源站把我 IP 给 ban 了
处理层 突变检测、阈值计算、去抖动 流处理引擎(Flink/Spark)、自定义规则 抖动窗口设太短,误报率飙升
存储层 存原始数据、告警事件、历史趋势 时序数据库(InfluxDB/Prometheus)+ 关系库 只用了关系库,查询历史趋势慢到崩溃
展示与处置层 告警展示、通知、自动化处置 Grafana、Webhook、自动伸缩脚本 通知链路没做降级,告警风暴时手机被打爆

3.2 关键组件选型与配置

这里不罗列所有技术栈,只讲跟 CRL 突变告警最相关的几个点。我个人建议先把消息队列加上——哪怕你现在流量不大。

3.2.1 消息队列:解耦的保险绳

我曾经有个项目,采集层直接把数据推到处理层。后来 CRL 源站响应变慢,采集线程全堵住,整个系统跟着雪崩。后来加了 Kafka,采集层只管往 topic 里扔,处理层自己消费,互不耽误。

我的配置建议:
• topic 分区数 = 处理层并行度 × 2(留点余量)
• 消息保留时间至少 7 天,方便回溯分析
• 采集数据带上时间戳和源标识,避免乱序

3.2.2 突变检测算法:别用死阈值

CRL 大小突变,简单比前一次大小差多少倍?不行的。我见过一个案例:某 CA 每天固定时间发新版 CRL,文件大小从 2MB 跳到 20MB 是常态,按固定倍数会天天误报。后来改用滑动窗口百分位 + 同比环比组合,才稳定下来。

我目前用的检测流程:
1. 取过去 7 天同一时间窗口的 CRL 大小,算 P95 和 P5 作为上下基线
2. 当前大小超出 [P5×0.8, P95×1.2] 则触发初级告警
3. 如果连续 3 个采样点都超限,升级为严重告警
4. 同时对比上一个采样点的变化率,超过 300% 直接上报
-- 简化版 SQL 示例:计算基线
SELECT 
  percentile_cont(0.95) WITHIN GROUP (ORDER BY size) AS p95,
  percentile_cont(0.05) WITHIN GROUP (ORDER BY size) AS p5
FROM crl_history
WHERE 
  source = 'source-a'
  AND ts >= NOW() - INTERVAL '7 days'
  AND EXTRACT(HOUR FROM ts) = EXTRACT(HOUR FROM NOW())
  AND EXTRACT(MINUTE FROM ts) BETWEEN EXTRACT(MINUTE FROM NOW()) - 5 AND EXTRACT(MINUTE FROM NOW()) + 5;

3.2.3 告警去抖动:降噪是关键

网络抖动、采集失败、源站临时故障……这些都会产生"假突变"。我的做法是:加一个 确认窗口。窗口内只记录状态变化,不立即发告警。比如连续 3 个采样点都异常,才认为真实突变。

注意: 窗口长度要跟采集周期匹配。如果每 5 分钟采一次,窗口设 15 分钟比较合理。设太短会漏告警,设太长会延迟响应。我曾经设过 30 分钟,结果 CRL 都更新两轮了,告警才出来……

3.3 架构总览图

下面这张图是我现在项目里用的架构,改了好几版才稳定。重点看数据流向和每一层的关键组件。

CRL 大小突变告警监控系统架构 采集 Agent 集群 定时拉取 CRL 文件 大小、时间戳、源标识 消息队列 (Kafka) topic: crl-raw 分区数 4,保留 7 天 流处理引擎 Flink / 自研 突变检测 + 去抖动 滑动窗口百分位 告警规则引擎 同比/环比/倍率 等级映射 抑制规则 存储层 时序库 (InfluxDB) 存指标 关系库 (PostgreSQL) 存告警事件 历史数据保留 90 天 展示 & 处置 Grafana 看板 Webhook → 钉钉/企微/邮件 自动处置脚本(可选) 说明:采集层只负责拉取,处理层做业务逻辑,存储层持久化,展示层负责交互。各层通过消息队列解耦,可以独立扩缩容。

3.4 高可用与降级策略

架构画出来容易,线上不崩才是本事。我经历过几次教训,后来加了几道保险:

  • 采集层多源备份:同一个 CA 的 CRL 至少配置两个拉取源,一个挂了自动切另一个。
  • 处理层幂等设计:同一个 CRL 大小重复处理不会产生重复告警。我用的方案是:检测结果写库时用 INSERT ... ON CONFLICT DO NOTHING。
  • 告警通知限流:同一告警规则 5 分钟内最多发 1 次通知。不然一次突变告警,企业微信能给你刷几百条。
  • 降级开关:如果消息队列积压超过阈值,直接跳过处理层,只记录原始数据到文件。宁可晚告警,也不能丢数据。
避坑指南(我亲身经历):
有一回存储层时序库磁盘满了,写入失败。但采集层还在正常工作,数据全积压在 Kafka 里。因为没监控存储层健康状态,直到用户反馈告警看板不更新才发现。后来我加了一个 存储层健康探针,心跳超时自动触发降级,把数据临时转存到本地文件。等恢复后再回放。

3.5 小结

这套架构我在三个不同的 CRL 监控项目中验证过。核心就是分层 + 解耦 + 降级。你不需要一次全部实现,可以先从采集+处理+存储三层搭起来,后面再加消息队列和展示层。记住一句话:先让数据跑通,再考虑优化。别一开始就搞微服务,容易把自己绕进去。