https://www.live400.com/newsdetail/id/67.html 为什么你的Prometheus监控"一切正常",用户却说系统崩了?-江苏立维-专注监控、运维服务(Zabbix|Prometheus|APM|日志|数据库)
  首页     >     新闻动态     >     为什么你的Prometheus监控"一切正常",用户却说系统崩了?

为什么你的Prometheus监控"一切正常",用户却说系统崩了?

发布日期:2026-01-22    阅读数:14
凌晨3点的噩梦


说个真事儿。上个月凌晨3点,我被一连串Prometheus告警吵醒。睁开眼一看,手机屏幕全是红:

  • api_response_time_p99 > 200ms

  • db_connection_pool_usage > 85%

  • error_rate_5m > threshold

我赶紧爬起来打开Grafana大盘,结果看到的画面让我一脸懵逼:

✅ CPU: 45%

✅ Memory: 62%

✅ Network: 正常

✅ Disk I/O: 正常

✅ 所有Pod都是Running状态

就这?那你告个毛线的警?

但半小时后,客服群炸了。大量用户投诉无法登录,有些甚至说"你们是不是服务器被黑了"。我当时脑子里就一个念头:我的监控明明说一切正常啊,到底哪里出问题了?

折腾到早上6点才查出来:某个第三方OAuth服务商的API响应从平时的50ms降到了3秒,导致我们的登录流程卡死,进而引发了一系列连锁反应。

最讽刺的是什么?我们的Prometheus里根本没有监控这个第三方依赖。因为它以前从来没出过问题,所以压根没想过要加监控。

这事儿让我开始重新思考一个问题:我们花了那么多时间搞监控,到底在监控什么?


你只能监控你知道的问题


干了这么多年监控,我发现大部分人对Prometheus的理解都有个根本性的误区——以为监控能发现所有问题

实际上呢?监控只能发现你预先知道会发生的问题

为什么这么说?咱们看看Prometheus的工作原理:

  1. 你定义一个metric:http_requests_total

  2. 你写个PromQL规则:rate(http_requests_total{status="500"}[5m]) > 0.01

  3. 然后配置Alertmanager:触发就发钉钉/短信

看出来了吗?这套流程的前提是你得提前知道要监控什么,阈值该设多少,什么情况算异常

这对成熟系统来说没问题。比如:

  • 磁盘快满了 → 这是"已知故障"

  • 内存泄漏 → 这是"经典问题"

  • MySQL主从延迟 → 这是"教科书案例"

但真实世界的故障呢?70%都是你从来没想到过的组合:

  • 某个微服务的重试逻辑有bug,在特定并发下会触发雪崩

  • Kubernetes调度器把所有新Pod调度到同一个节点,导致热点

  • 某个Java服务的GC暂停时间从5ms突然变成500ms,但还没到你设的阈值

  • 某个定时任务的cron表达式写错了,从每天一次变成每秒一次

这些问题的"症状"可能在Prometheus里显示为"正常范围内的波动"。等你发现的时候,用户已经跑路了。就像下棋,监控只能防住你复盘过的棋路,但对手总会下出新的变化。


三个让监控失效的陷阱


陷阱1:维度选择的盲区

大家都知道监控要看"四个黄金信号":延迟、流量、错误、饱和度。这套方法论没毛病,但问题在于——它假设系统行为可以用这四个维度完整描述。

实际上呢?有些故障根本不在这些维度上:

案例A - 数据正确性问题

去年遇到过一次,所有监控指标都正常,但用户看到的账户余额是错的。后来查出来是某个字段更新的SQL写错了,本该更新A表结果更新了B表。

  • P99延迟?正常 ✅

  • 错误率?正常 ✅

  • QPS?正常 ✅

但数据已经脏了,Prometheus根本看不到。

案例B - 长尾效应

有次压测,看P50和P99都很漂亮。结果上线后收到投诉,说某些VIP用户总是超时。后来才发现是P99.9的请求全挂了,而那0.1%刚好是付费用户。

你的Prometheus可能只采集到P99,P99.9根本没算。结果就是:大盘数据漂亮,核心用户骂娘

陷阱2:Cardinality爆炸的反噬

说到Prometheus,就不得不提label cardinality这个大坑。

刚开始用Prometheus的时候,我也犯过这个错误:觉得标签越详细越好,于是给metric加了一堆label:

http_requests_total{
  user_id="12345",          // 100万用户
  endpoint="/api/xxx",      // 500个接口
  status="200",             // 10种状态码
  region="cn-beijing",      // 20个地区
  device_type="iOS"         // 50种设备
}

算一下:100万 × 500 × 10 × 20 × 50 = 50亿时间序列

结果是什么?Prometheus直接OOM,监控系统成了故障源头。

后来我明白了一个道理:监控不是越详细越好,而是要抓住核心矛盾。就像拍照,如果每张照片都是100GB的原图,你的硬盘再大也不够用,而且根本看不过来。

现在我的原则是:核心告警不超过7个,标签不超过5个维度,时间序列控制在100万以内。宁可少而精,不要多而乱

陷阱3:相关性不等于因果性

Prometheus最擅长的是发现相关性,但最不擅长的是找因果关系。

举个例子,你看到Grafana上"数据库CPU飙升"和"API响应变慢"同时发生,第一反应肯定是:"数据库有问题!"

但真实原因可能是:

  • 某个测试同学误连了生产库,跑了个全表扫描

  • 某个定时任务配置错了,从每天1次变成每秒1次

  • Redis缓存突然失效,查询全打到DB

  • 某个爬虫在暴力爬取你的API

Prometheus只能告诉你""(CPU高了),但无法告诉你""(为什么高)。

就像看电影的截图:你看到主角第1分钟在笑、第5分钟在哭、第10分钟倒地了,但你不知道中间发生了什么。故障调试需要的不是截图,而是完整的录像——这就是为什么我们需要分布式追踪。


从"监控思维"到"可观测性思维"


讲真,这两年"可观测性"这个词被各种厂商吹得神乎其神,搞得像是买了个Observability平台就能解决所有问题似的。

但我理解的可观测性,本质上就一句话:承认监控有局限,所以要保留足够的上下文信息,让你在出问题时能快速调试 

对比一下:

监控思维可观测性思维
"这个指标要不要加监控?""出问题时我能快速定位吗?"
预定义指标+阈值保留高精度原始数据
聚合数据(P99、平均值)原始事件(traces、logs)
被动响应告警主动探索分析

具体怎么做?我总结了几个实战经验:

1. 给每个请求一个TraceID

这个不用多说了,OpenTelemetry已经是标准了。关键是要端到端贯穿:从浏览器、到网关、到微服务、到数据库,全程带着TraceID。

出问题的时候,拿着TraceID在Jaeger里一搜,整条链路的耗时、依赖关系、错误点一目了然。

2. 监控要"极简主义"

SRE那本书里有句话我特别认同:核心告警不要超过5-7个。

为什么?因为告警太多等于没告警。你的团队会麻木,真正的故障反而被淹没了。

我现在的原则是:

  • 每个告警必须对应一个Runbook(明确的处理流程)

  • 季度内查看不到1次的指标,直接删掉

  • 能用日志解决的,就不要加监控

3. 别忘了监控"变更"

这个经常被忽略。我们花大力气监控CPU、内存、QPS,但往往忘了最危险的因素:变更。 

统计一下你们过去一年的故障,至少70%都是变更引起的:

  • 代码部署

  • 配置修改

  • 基础设施升级

  • 依赖版本变更

所以我现在的做法是:把所有变更事件都打到Prometheus的Annotations里,在Grafana上显示为垂直线。出问题的时候,一眼就能看出"是不是刚刚部署了什么"。


最后想说的


写这篇文章的时候,我翻了翻去年的oncall记录。印象最深的不是那些半夜被吵醒的时刻,而是那些监控系统什么都没发现,用户却已经炸了的瞬间。

监控系统就像汽车的仪表盘:它能告诉你油量、速度、转速,但它无法告诉你"为什么发动机异响",更无法告诉你"前方会不会堵车"。

监控只能发现已知问题——这不是监控的缺陷,而是复杂系统的本质。

所以我的建议是:

✅ 承认监控有局限

✅ 为系统设计"可调试性"(logs、traces、metrics三件套)

✅ 保留出问题时需要的"证据"

✅ 培养团队的调试直觉和RCA文化

最后借用Bryan Cantrill的一句话:"Debugging is iterative hypothesis testing." 监控给你假设的起点,但真正找到根因,靠的还是你对系统的理解。

新闻搜索

相关新闻

云安全风险发现,从现在开始
返回顶部-立维
公众号
关注微信公众号
电话咨询
服务热线:400-006-8618
项目咨询
项目合作,欢迎发邮件咨询
liveserver@live400.com