第三章:性能监控体系

性能监控这事儿,我做了十几年,踩过的坑比走过的路还多。很多人一上来就堆工具,Prometheus 装了,Grafana 配了,SkyWalking 也上了,结果线上出了故障还是两眼一抹黑。为什么?因为没搞懂监控的本质。

监控说白了就三件事:指标、日志、链路。这三样东西,缺一个你都没法真正看清系统的全貌。我习惯把它们叫做「监控三要素」,今天咱们就一个一个拆开来讲。

3.1 监控三要素:指标、日志、链路

先说说这三者各自管什么。

  • 指标(Metrics):告诉你系统「现在怎么样」。比如 CPU 用了多少、QPS 多少、错误率多少。它是数字化的,适合做告警和趋势分析。
  • 日志(Logs):告诉你系统「发生了什么」。比如某次请求报了什么错、参数是什么。它是文本化的,适合做问题定位。
  • 链路(Traces):告诉你系统「为什么慢」。比如一个请求经过了哪些服务、每个服务花了多少时间。它是结构化的,适合做性能瓶颈分析。

你想想看,如果只有指标,你只知道 CPU 飙高了,但不知道是哪个接口导致的。如果只有日志,你只能一条一条翻,效率极低。如果只有链路,你只能看到调用关系,但看不到资源消耗。所以,三者必须配合使用。

核心观点:指标用于告警,日志用于定位,链路用于分析。三者缺一不可。

我在项目中遇到过一种情况:某次线上故障,指标显示接口响应时间从 50ms 飙到了 5s,但日志里没有任何错误。后来查链路才发现,是下游的一个 Redis 集群超时了。你看,没有链路数据,你根本不知道问题出在哪一环。

3.2 Prometheus + Grafana 搭建

说到指标监控,Prometheus 和 Grafana 基本是标配了。Prometheus 负责采集和存储,Grafana 负责展示和告警。这套组合我用了很多年,稳定、灵活、社区活跃。

3.2.1 Prometheus 核心概念

Prometheus 的数据模型其实很简单:时间序列。每个时间序列由 metric 名称和一组 key-value 标签唯一标识。比如:

http_requests_total{method="GET", endpoint="/api/user", status="200"} 1024

这个数据表示:GET 请求 /api/user 接口,返回 200 的次数是 1024。Prometheus 会定期拉取这个数据,存储到本地。

它的架构也很清晰:

  • Prometheus Server:核心组件,负责拉取数据、存储、查询。
  • Exporters:数据采集器,比如 node_exporter 采集机器指标,mysqld_exporter 采集数据库指标。
  • Pushgateway:用于短期任务的指标推送。
  • Alertmanager:负责告警管理。

小技巧:我个人习惯把 Prometheus 的存储保留期设为 15 天。太短了查不到历史数据,太长了磁盘扛不住。如果你需要长期存储,可以搭配 Thanos 或 VictoriaMetrics。

3.2.2 搭建步骤

搭建其实不复杂,我直接给一个最简的 docker-compose 配置:

version: '3'
services:
  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin

对应的 prometheus.yml 配置:

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'node'
    static_configs:
      - targets: ['localhost:9100']

启动之后,访问 localhost:9090 就能看到 Prometheus 的 UI,访问 localhost:3000 就是 Grafana。在 Grafana 里添加 Prometheus 数据源,然后导入一个现成的 Dashboard(比如 Node Exporter Full),你就能看到机器的各项指标了。

注意:我曾经因为 scrape_interval 设置得太短(5s),导致 Prometheus 把生产环境的机器 CPU 打满了。建议生产环境至少设到 15s,甚至 30s。监控本身不能成为性能瓶颈。

3.2.3 告警配置

光有图表不够,还得有告警。Prometheus 的告警规则写在 rules 文件里:

groups:
  - name: node_alerts
    rules:
      - alert: HighCPUUsage
        expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Instance {{ $labels.instance }} CPU usage > 80%"

这个规则的意思是:如果某个机器的 CPU 使用率超过 80%,持续 5 分钟,就触发告警。Alertmanager 收到告警后,可以发邮件、钉钉、Slack 等等。

3.3 APM 工具:SkyWalking 与 Pinpoint

指标和日志都有了,但你还缺一样——链路追踪。这就是 APM(Application Performance Management)工具干的事。市面上主流的 APM 工具有 SkyWalking、Pinpoint、Jaeger、Zipkin 等。我个人用得最多的是 SkyWalking 和 Pinpoint。

3.3.1 SkyWalking

SkyWalking 是国产开源项目,对 Java 生态支持非常好。它的核心优势是:无侵入。你只需要在启动参数里加一个 javaagent,就能自动采集链路数据。

java -javaagent:/path/to/skywalking-agent.jar \
     -Dskywalking.agent.service_name=my-service \
     -Dskywalking.collector.backend_service=127.0.0.1:11800 \
     -jar my-app.jar

启动之后,SkyWalking 会自动拦截 HTTP、RPC、数据库等调用,生成链路数据。你可以在它的 UI 上看到:

  • 每个请求的完整调用链
  • 每个节点的耗时
  • 错误信息
  • 服务拓扑图

我记得有一次,一个接口特别慢,从日志看 SQL 执行时间正常,但接口就是慢。后来用 SkyWalking 一看,发现是 HTTP 调用下游服务时,连接池满了,请求在排队。这种问题,没有链路追踪根本查不出来。

3.3.2 Pinpoint

Pinpoint 是韩国团队开发的,跟 SkyWalking 类似,也是基于字节码增强的 APM 工具。它的特点是:数据粒度更细。Pinpoint 能展示每个方法的调用次数、响应时间、甚至每个参数的采样值。

但 Pinpoint 也有缺点:资源消耗大。我曾在生产环境试过 Pinpoint,发现它会把 JVM 的 GC 时间拉高不少。如果你的机器资源比较紧张,建议优先考虑 SkyWalking。

特性 SkyWalking Pinpoint
部署复杂度 低(支持单节点) 中(依赖 HBase)
资源消耗 低 高
数据粒度 中 细
社区活跃度 高(中文社区) 中
适用场景 生产环境首选 测试环境/问题排查

我的建议:生产环境用 SkyWalking,稳定、轻量、够用。如果你需要做深度的代码级性能分析,可以临时部署 Pinpoint,用完就关掉。

3.4 知识体系总览

下面这张图是我自己整理的监控体系结构,你可以对照着理解:

性能监控体系总览 监控三要素 指标(Metrics) 日志(Logs) 链路(Traces) 工具层 Prometheus + Grafana ELK / Loki SkyWalking / Pinpoint 数据层 时序数据库(TSDB) 全文检索(ES) 链路存储(H2/ES)

从这张图你可以看到,监控体系分三层:要素层定义你要监控什么,工具层解决怎么采集和展示,数据层解决怎么存储和查询。每一层都有对应的技术选型。

嗯,到这里,监控体系的核心内容就讲完了。记住一句话:没有监控的系统,就像闭着眼睛开车。你永远不知道下一秒会撞上什么。

避坑指南:我曾经在一个项目里,把所有监控指标都堆到同一个 Grafana Dashboard 上,结果图表太多,根本看不清楚。后来我学乖了,按服务拆分 Dashboard,每个服务一个,只展示关键指标。简洁,才能高效。

想要更多资料,联系可可