深入理解监控工具:从线上崩盘到稳如老狗的血泪史

Spring打工人
2025-12-13 17:25
阅读 757

大家好,我是老张,三线城市某互联网公司后端组的技术负责人。在这儿干了快两年,带了个 5 人小团队,日常主要搞微服务架构、中间件封装和背锅(笑)。最近迷上了 Rust,感觉这语言简直有毒——写起来痛不欲生,跑起来稳如泰山,特别适合我们这种“既要又要还要”的小公司。

今天这篇博客,源于去年双11期间的一次“史诗级”线上事故。事情是这样的:我们的核心订单服务在流量高峰时直接挂掉,用户下单失败率飙到 40%,运维那边疯狂@我,产品在群里刷屏“快救救孩子”,测试同事默默发了个“又来了.jpg”。而我当时,正躺在沙发上刷 Rust 官方文档,美其名曰“技术预研”……

结果,被领导一个电话叫回公司,凌晨三点对着满屏的红色告警,差点把 MacBook 砸了。

那时候的“监控”,其实只是个摆设

说实话,在那次事故之前,我们也“有”监控。Prometheus + Grafana + Alertmanager 一套三件套早就搭好了,Kafka 消息堆积、MySQL QPS、Redis 命中率……该有的指标都有。但问题是——这些数据根本没人在意

为什么?因为:

  • 告警阈值是随便抄的网上模板,比如“CPU > 80% 就报警”,结果开发机跑 CI/CD 的时候天天误报;
  • 没人定义什么是“业务异常”——订单创建失败率超过 5%?没人知道这个数字;
  • 运维同学只关心机器是不是活着,开发只关心代码能不能跑,产品只关心 KPI 达没达成,监控成了三不管地带

更惨的是,面试的时候我还经常问候选人:“你们怎么设计监控体系?” 结果自己公司的监控连“综合可观测性”都谈不上,纯属形式主义。后来有个实习生私下跟我说:“张哥,你问的那些监控面试题,咱们自己都做不到啊。” 我当场尴尬得脚趾抠出三室一厅。

重新定义“监控”:不是看数据,而是看业务

这次事故后,老板拍板:“监控必须重做,下个月上线前搞定,不然年终奖泡汤。” 行吧,为了那点年终奖(以及跳槽简历能写点干货),我和团队花了两周时间,彻底重构了我们的监控体系。

核心思路就一条:监控不是为了看服务器有没有死,而是为了保障业务正常运转

于是我们做了三件事:

1. 从业务出发定义 SLO(Service Level Objective)

以前我们只监控基础设施,现在我们先问产品:“什么情况下用户会骂娘?”

答案很直接:

  • 用户下单失败率 > 2%
  • 支付回调延迟 > 5s
  • 库存扣减不一致(超卖 or 超买)

基于这些,我们反推出每个微服务的 SLO:

  • 订单服务 P99 响应时间 < 800ms
  • 支付回调成功率 > 99.95%
  • 库存服务消息处理延迟 < 3s

📌 开发心得:SLO 不是技术指标,而是业务承诺。别再拿“QPS 1万”当 KPI 了,用户不在乎你扛了多少并发,只在乎他能不能成功下单。

2. 构建“综合可观测性”三层模型

我们参考了 Google 的“黄金信号”理论,但结合小公司实际做了简化:

层级 监控内容 工具 负责人
基础设施层 CPU、内存、磁盘、网络 Prometheus Node Exporter 运维
应用层 接口耗时、错误率、GC、连接池 Prometheus + Micrometer 开发
业务层 订单成功率、支付转化率、库存一致性 自定义埋点 + Flink 实时计算 开发 + 数据

重点来了:业务层指标必须由开发主动埋点。我们用 Spring Boot Actuator 暴露 /metrics,再通过 Prometheus 抓取。比如订单创建失败次数:

// OrderController.java
@Autowired
private Counter orderCreateFailedCounter;

@PostMapping("/create")
public ResponseEntity<?> createOrder(@RequestBody OrderRequest req) {
    try {
        orderService.create(req);
        return ok();
    } catch (Exception e) {
        // 关键!记录业务失败
        orderCreateFailedCounter.increment();
        log.error("创建订单失败", e);
        return error("系统繁忙");
    }
}

然后在 Grafana 里画出“每分钟失败订单数 / 总订单数”的曲线,一旦超过 2%,立刻触发企业微信告警。

3. 告警分级 + 自动化响应

以前是“一炸全群”,现在我们搞了三级告警:

  • P0(红色):业务中断(如下单完全不可用)→ 自动打电话给 on-call 开发 + 发短信给技术负责人(就是我)
  • P1(橙色):业务降级(如失败率 > 5%)→ 企业微信群 @所有人 + 钉钉机器人播报
  • P2(黄色):潜在风险(如 Redis 连接池 > 80%)→ 只发给对应服务负责人,不打扰他人

更狠的是,我们还写了自动恢复脚本。比如 Kafka 消费堆积超过 10w 条,自动扩容消费者实例(通过 Kubernetes HPA),并通知运维检查下游服务。

踩过的坑:别学我!

当然,过程中也踩了不少坑,分享几个血泪教训:

坑1:过度监控 = 无效噪音

一开始我们给每个方法都加了耗时监控,结果 Grafana 面板密密麻麻全是线,根本看不出重点。后来我们砍掉了 70% 的非核心指标,只保留影响业务链路的关键节点

最佳实践:只监控你能 action 的指标。如果看到告警你不知道该干嘛,那就删掉它。

坑2:日志、指标、链路追踪要打通

我们用 Jaeger 做链路追踪,但早期日志里没打 TraceID,出了问题根本对不上。后来强制要求所有日志输出格式包含 trace_idspan_id

[2023-11-05 14:23:01] INFO [trace_id=abc123, span_id=def456] OrderService - 扣减库存成功

这样在 Grafana 里点一下异常指标,就能直接跳转到对应的 Jaeger 链路,效率翻倍。

坑3:别忽视“运营视角”

有一次产品跑来问我:“昨天促销活动效果怎么样?” 我只能翻数据库查订单量。后来我们把关键业务指标直接暴露给运营——他们在内部 BI 系统里就能看到实时下单人数、地域分布、热门商品,再也不用半夜敲我微信了。

💡 开发心得:监控不仅是技术活,更是协作工具。让产品、运营也能看懂数据,团队摩擦少一半。

效果如何?稳了!

重构后的第一个大促(今年 618),我们实现了:

  • 0 次 P0 级故障
  • 平均故障定位时间从 45 分钟降到 8 分钟
  • 产品团队首次在活动期间自主分析用户行为,不用等我们导数据

最爽的是上周五晚上,我正准备下班去吃火锅,突然收到 P1 告警:“支付回调延迟升高”。我打开 Grafana,发现是第三方支付网关响应变慢,不是我们的锅!立马截图甩给合作方,然后潇洒地关电脑走人。

那一刻,我感受到了什么叫“稳如老狗”。

写在最后:监控不是成本,是保险

很多人觉得监控是“额外工作”,尤其小公司资源紧张,总想省掉。但我想说:一次线上事故的损失,够你搭十套监控系统了

而且现在开源工具这么成熟,Prometheus + Grafana + Loki + Tempo 这套组合拳,几乎零成本就能搭建起完整的可观测性平台。我们甚至用 Rust 写了个轻量级的日志收集 agent(别问,问就是 Rust 真香),内存占用比 Filebeat 低 60%。

如果你也在准备跳槽,建议好好研究监控体系——这绝对是高级工程师和普通 CRUD 码农的分水岭。面试官问“你怎么保障系统稳定性”,你要是只会说“我加了 try-catch”,怕是要被挂墙头。

总之,监控这事,早做早享受,晚做火葬场。希望我的血泪史能帮你少走点弯路。

对了,下周我打算写一篇《用 Rust 重写日志收集器:性能提升 3 倍的秘密》,感兴趣的话记得关注。毕竟在我们这种三线小厂,不卷点新技术,怎么好意思跟一线大厂抢人呢?(手动狗头)


附:我们的核心监控配置片段

# prometheus.yml - 业务指标抓取
scrape_configs:
  - job_name: 'order-service'
    static_configs:
      - targets: ['order-svc:8080']
    metrics_path: '/actuator/prometheus'
    relabel_configs:
      - source_labels: [__address__]
        target_label: service
        replacement: 'order'

# alert.rules.yml - 业务告警规则
groups:
- name: business-alerts
  rules:
  - alert: HighOrderFailureRate
    expr: rate(order_create_failed_total[5m]) / rate(order_create_total[5m]) > 0.02
    for: 2m
    labels:
      severity: warning
    annotations:
      summary: "订单创建失败率过高"
      description: "当前失败率 {{ $value | humanizePercentage }}"

注:以上配置已脱敏,实际使用请根据业务调整阈值和标签。


作者:老张,三线城市互联网公司技术负责人,Rust 爱好者,梦想是写出零 bug 的代码(虽然至今未实现)。
声明:本文纯属个人经验分享,如有雷同,说明你也经历过线上崩盘 😅

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝