工程治理
收录于 工程治理体系
指标开始贴业务以后,监控为什么还会越做越重
上一篇写的是指标为什么要映射业务结果、辅助定位并进入增量准入。这一篇继续往下看:多租户维度为什么会把 Metrics 自己拖重,告警为什么不能只是把异常一股脑扔给人。
上一篇《指标做了,然后呢》里,我主要在讲一件事:很多系统有图也有告警,但这些东西照不出业务结果,也带不动处理动作。要补的不只是接口 RT、线程池活跃数、MQ 堆积这些技术指标,还要补结果指标、过程信号、定位维度,以及增量准入。
但那篇写完以后我发现,事情还没到头。
因为指标一旦开始贴业务,监控系统很快就会遇到另一组问题。
一组问题出在 Metrics 本身。多租户场景里,很多团队很自然就会把租户、接口、区域、下游系统这些信息一路打进指标。早期这样做很顺,业务也觉得直观;可维度一多,时序数、查询成本和面板理解成本会一起往上走,最后监控系统自己先变重。
另一组问题出在告警。指标和阈值都补起来以后,系统确实更容易“响”了,但值班人不一定更容易接近问题。基础依赖一抖,数据库超时、队列积压、消费失败、业务退化可以同时冒红。每条告警单看都是真的,现场却还是不知道先处理哪一个。
所以这篇我只继续往下讲两件事:第一,为什么监控补到后面,问题会从“看不见”变成“承不住”;第二,为什么一套线上系统不能只是机械地报警,而必须具备收敛和抑制能力。
监控补到后面,问题会从“缺”变成“重”
很多工程能力都有这个阶段变化。
早期最大的问题是没有。没有业务结果指标,没有关键链路告警,没有统一面板,线上一出事就只能翻日志、查 DB、看群消息。这个阶段怎么补都不算过分,因为系统本来就在盲飞。
不过补到后面,核心矛盾就变了。
这时候最尴尬的问题已经换了方向,集中在下面三件事:
- 指标越来越多,但真正能帮人判断的信号没有同比增长
- 维度越来越细,但查询和理解成本一起上去了
- 告警越来越全,但现场还是不知道先看哪个
也就是说,监控往前走到一定阶段以后,问题已经从“采不采”“报不报”,转向了“边界怎么收”“复杂度怎么控”“什么信息该留在哪一层”。
如果这一步没想清,系统就很容易进入一种假繁荣状态:图越来越多,告警越来越密,面板看上去越来越完整,但故障真来了,大家还是回到最原始的路径,靠日志、经验和群消息去拼真相。
东西明明做了,现场却还是靠人扛。
多租户指标为什么早期好用,后面会变重
多租户监控最容易踩的坑,恰恰是它太容易在早期成立。
业务刚起步的时候,租户数不多,链路也还简单。为了让业务方能直接看懂,最顺手的办法就是把 tenant_id 打进指标里。谁失败率高,谁延迟大,谁积压明显,按租户一切就出来了,看着非常合理。
而且这条路还有一个很强的诱惑:它太顺了。业务本来就是按租户思考问题的,你把租户打到图里,业务很快就能提需求,平台也很容易继续往前补。于是后面的维度会自然长出来:
- 再加接口
- 再加区域
- 再加状态码
- 再加下游系统
- 再加消息类型
- 再加产品形态或版本
这些维度单独看都没错,问题出在它们会一起乘起来。
一开始十几个、几十个租户时,你几乎感觉不到压力;到了几百个租户,再叠上接口、区域、状态码、下游系统,Metrics 存储、查询和聚合成本就会明显抬上来。最开始是为了让业务看得更清楚,后面却可能变成谁都看不清,甚至连系统自己都快承不住了。
这里最容易出现的误判,是把“现在这样做没问题”误以为“以后一直这样做也没问题”。
租户维度不是不重要,问题是它不能无限度地往 Metrics 里长。业务对象和指标承载方式,不是同一件事。前者回答的是“业务按什么管理”,后者回答的是“哪些信息值得稳定地聚合、查询和告警”。
不是所有业务细节都该进 Metrics
后来有一个判断变得很清楚:指标不是用来承载所有业务细节的。
Metrics 最擅长的,是统计、趋势和聚合。它很适合回答下面这些问题:
- 哪个租户的失败率开始抬头了
- 哪条链路的 P99 变差了
- 哪个区域的吞吐明显下降了
- 哪类任务的积压正在持续增长
这些问题都很重要,因为它们能帮你尽快看见异常,尽快判断影响面。
但 Metrics 不擅长回答另一类问题:
- 到底是哪一次请求出了错
- 哪一笔任务卡住了
- 是哪条调用把整体时延拖慢了
- 具体报错长什么样,上下文是什么
这类信息当然值钱,但它们天然更适合落在日志和 Trace 里,而不是硬塞进 Metrics。
如果为了定位方便,把越来越多高细节、高上下文的信息都想办法打成指标,最后通常会出现两头都不讨好:一边是指标越来越重,另一边是定位依然不够快。因为 Metrics 再怎么细,也很难替代日志和 Trace 本身承载的上下文。
所以更稳的做法,是别再给 Metrics 加负担,把三层信息分清:
- Metrics 负责告诉你:哪里开始不对了
- 日志负责告诉你:具体发生了什么
- Trace 负责告诉你:问题在链路里怎么传导
我后来会更看重 Exemplars,也是在这个语境里。
Exemplars 值钱的地方,就是给指标留了一条继续往下查的入口。图上某个时间点已经能看见异常了,那就应该能顺着这个异常,尽快跳到那次具体调用、那条具体日志、那个确实有上下文的样本上。
告警系统最怕的,不是不响,而是把一件事拆成十几条提醒
如果说多租户指标的问题,本质上是在问“什么该进 Metrics”,那告警系统的问题,说到底就在问“什么该先到人面前”。
一开始做告警时,最容易落入一种直觉:能报出来,总比报不出来强。
这个想法只对了一半。
线上最糟糕的情况,往往是同一件事衍生出了一大片告警。数据库一抖,下游服务超时、队列积压、消费重试、业务失败一起冒红;某个基础依赖出问题,最后值班人收到的是十几条不同系统、不同层级的提醒。
这些告警从单条看都是真的,但从现场处理角度看,它们并没有帮助。因为人在现场最需要的,是先知道“最可能的根因在哪,先处理哪个最值钱”,光知道“很多地方都坏了”帮不上忙。
所以告警系统最怕的,不是不响,而是乱响。
它一旦只是机械地把异常全扔给人,就会制造一种很典型的错觉:系统好像非常敏感,实际上值班人的注意力已经被打碎了。告警越多,越难判断优先级;提醒越密,越容易让人先静音。
所以我后来不太愿意把“先看宿主机,再看中间件,再看应用”这种经验,当成告警治理方案。
这当然是一套排障顺序,但它回答的是“人已经被告警淹没以后,该怎么手工排查”。它没有回答另一个更关键的问题:系统能不能在把告警推给人之前,先帮忙做一轮信息压缩。
前者是经验。后者才是能力。
告警收敛真正值钱的地方,是减少无效注意力消耗
做下来的体感是,业务系统里的告警收敛,核心在于它承认人的注意力很贵,规则高不高级反而次要。
故障现场最稀缺的不是数据,而是判断力。值班人不缺图,不缺日志,也不缺通知。缺的是在混乱里快速抓住重点的能力。
所以一套更有用的告警系统,至少应该尝试先做这几件事:
- 判断这批告警是不是本质上一件事
- 尽量把更上游、更接近根因的告警优先打出来
- 把明显的衍生症状折叠掉,而不是全部平铺给人
- 对同一时间窗内重复出现的同类提醒做抑制,而不是不停重发
目的很简单:让现场少一点无效注意力消耗。
把上面两个问题串起来看,从维度爆炸到告警收敛,压缩大致要在这几个位置发生:
flowchart TD
A["tenant_id 打进指标"] -->|"维度自然往上长"| B["× 接口 × 区域 × 状态码 × 下游"]
B -->|"一起乘起来"| C["时序数爆炸"]
C -->|"存储 / 查询 / 聚合成本抬升"| D{"信息该留在哪一层?"}
D -->|"统计 / 趋势 / 聚合"| E["Metrics:哪里不对了"]
D -->|"具体请求与上下文"| F["日志 + Trace"]
E -.->|"Exemplars 串联"| F
E --> G["告警触发"]
G -->|"基础依赖一抖"| H["多层告警并发"]
H -->|"同源合并 / 根因优先"| I["收敛与抑制"]
I --> J["值班人只收关键信号"]
这一篇想补上的,其实还是“边界”
回头看,这篇里的两个问题,一个是多租户指标,一个是告警噪音,看起来不完全像一件事,但其实都在讨论同一个问题:
监控系统到底该把什么信息放在哪一层。
上一篇《指标做了,然后呢》更关心的是,指标能不能贴到业务结果上,能不能真的进入处理路径。
这一篇更想补的是,指标即便开始贴业务了,也不能什么都往里装;告警即便开始配起来了,也不能只管响,不管收。否则监控建设做着做着,很容易又变成新的系统负担。
前一篇在讲“别让监控只剩下一堆数字”。这一篇在讲“别让监控为了更有用,最后把自己也做重了”。