第14篇 从监控到可观测性:体系化总结与演进路线

0 阅读14分钟

前面十三篇,从零把 Prometheus 拉起来,一路装了 node_exporter、Spring Boot 的 Actuator、Nginx、Blackbox、SQL Exporter,中间复盘了指标怎么选(RED / USE / 黄金信号)、告警怎么治理、Grafana 怎么做下钻和统一面板、报告怎么写、高可用和长期存储怎么落地,最后把安全这扇门也顺手关上了。

本篇目标:

  • 把前 13 篇收敛成一张能挂在墙上的体系地图;
  • 提供一套可参考的演进路线,让现在这套 Prometheus 体系平滑地长成可观测性平台,而不是推倒重来。

一句话:前面是"怎么建",本篇是"建完了怎么用、怎么长"。

一、先复盘:前十三篇建了什么

一张表整理:

篇号主题解决的问题所在层
1体系全景与基础环境搭建把 Prometheus / Grafana / Alertmanager 跑起来采集层·地基
2服务发现:动态目标管理实例 IP 漂移,不用手工改配置采集层·地基
3主机层监控:node_exporter主机 CPU / 内存 / 磁盘 / 网络采集层·对象
4Spring Boot 应用监控应用 HTTP / JVM / 连接池采集层·对象
5Nginx 监控流量 / 连接 / 性能三条线采集层·对象
6依赖服务探活:Blackbox Exporter外部视角拨测,补内部盲区采集层·对象
7业务数据监控:SQL Exporter库里的业务数据变成指标采集层·对象
8关键指标分析方法:RED / USE / 黄金信号几百条曲线收敛到几十条方法层
9告警体系设计:Alertmanager让每条通知都值得处理响应层
10Grafana 可视化进阶变量、下钻、统一面板呈现层
11监控报告:SLO / SLI 与数据分析把数据变成决策决策层
12高可用与长期存储采集不断、告警不哑、数据存得久生产化
13监控安全与权限治理把默认敞开的门锁上生产化

串起来就是一个闭环:

采集(1~7) ──► 方法收敛(8) ──► 告警响应(9)
    ▲                                   │
    │                                   ▼
 优化采集 ◄── 决策改进(11) ◄── 可视化呈现(10)
                                        │
                            生产化保障:高可用(12)+ 安全(13)

⚠️ 注意:很多团队只建了闭环的一条边。"采集"做得挺全,"告警"配了一堆,但没人做"方法收敛"和"决策改进",结果就是采集量每年涨、告警量每年涨、真正被处理的问题却不见少。监控的完备性从来不取决于采集量,而取决于这个闭环有没有转起来。

二、散落在各篇里的六条"地基"

有六条原则在前面文章中反复出现,可参考制定进监控规范里:

1)标签规范是所有聚合、抑制、下钻的索引

svc 和 type 这两个标签,是作为命名约定埋下的,但真正的重量在后面几篇才显出来:第 8 篇跨层抑制靠它,第 9 篇分组和抑制主键靠它,第 10 篇下钻链路靠它。改一次标签规范,上面所有规则会悄悄失效,而且不报错。

2)"采集—展示—告警"必须成环

第 5 篇和第 8 篇都强调了同一句话:监控的完备性不取决于采集量,而取决于闭环是否成立。采集保证可追溯、展示保证可感知、告警保证可执行。缺任何一环,监控就退化成"事后翻日志"的工具。

3)先做减法,再做加法

第 8 篇把几百条曲线砍到几十条关键项;第 12 篇反复算账,存储压力的大头往往是基数而不是天数,与其急着上 Thanos,不如先分层抓取、先裁掉不看的序列。很多"需要新架构"的场景,其实是列表没做减法。

4)阈值要贴着业务基线走,别静态钉死

静态阈值是告警疲劳的头号来源。第 3、5、8 篇都提到:QPS 这类指标看环比/同比波动,没有绝对阈值;磁盘、CPU 的阈值也要结合业务基线动态校准。

5)监控组件要独立部署、隔离故障域

第 7 篇那条"独立部署是底线"值得单独拎出来:业务数据 Exporter 绝不内嵌进业务应用,共享资源、共享故障域,最后监控反而会拖垮被监控的对象。

6)默认即不安全,最小权限

第 13 篇的结论:Prometheus、Grafana、exporter 出厂几乎都是敞开或弱口令的。第一个动作永远是关默认、收端口、上认证;凭据绝不进配置文件。

三、监控 ≠ 可观测性:先理清概念

最直白的分法:

维度监控(Monitoring)可观测性(Observability)
回答的问题已知的已知未知的未知
工作方式预设指标 + 阈值,超了就告警拿到底层原始数据,临场提问、自由组合
依赖你事先猜到要监控什么不需要事先猜全,数据够原生就能事后推断
典型场景磁盘会不会满、QPS 多少"为什么欧洲用户周三下午下单变慢"

举个例子。磁盘快满、CPU 飙高、5xx 上涨,这些是监控能覆盖的,因为在第 3、4 篇就把这些指标预设好了。

但如果是"某个新上线的功能,只在特定机型 + 特定时段偶发超时",事前根本想不到要配什么指标,这时候就轮到可观测性:指标看到异常,日志能下钻到具体报错,链路能追到是哪一次调用、哪一个依赖慢。

行业里常说的三支柱(Three Pillars)就是这个意思:

  • Metrics(指标)——聚合的数值。便宜、适合看趋势和告警。
  • Logs(日志)——离散的事件。细节最全,适合下钻根因。
  • Traces(链路)——一次请求跨服务的完整轨迹。适合定位分布式系统里"慢在哪一跳"。

⚠️ 注意:本系列只聚焦介绍了 Metrics 一根柱子。 监控是可观测性的子集;往可观测性演进,不是推翻监控,而是补上另外两根柱子,再用统一的上下文(标签、trace_id)把它们串成一张网。

四、演进路线:从一根柱子到三根柱子

演进这件事,最怕两种失败:一种是一步到位,直接奔着大平台去,预算和人力都跟不上,半年后烂尾;另一种是原地打转,一直停在指标阶段,遇到指标说不清的问题只能靠猜。

正确的姿势是痛点驱动、分阶段走。每一阶段都先问一句:"我们现在是不是真的被这件事卡住了?"卡住了再上,不卡就别上。下面是一条参考路线,从阶段 0 到阶段 4,对应不同成熟度。

阶段 0:指标监控(现状)

即本系列 1~13 篇所涉及的东西:Prometheus 采集 + 方法收敛 + 告警治理 + Grafana 可视化 + 报告决策 + 高可用 + 安全。

本阶段已经能满足个人和中小企业的绝大部分需求。 如果团队规模不大、系统不复杂,到本阶段已经够了,不必为了"可观测性"三个字强行上马。

继续演进的触发信号: 出现"指标看到了异常,但说不清为什么"的情况越来越多,比如 5xx 涨了,指标只能告诉你哪个接口、哪个实例,但告诉不了你具体报的什么错、慢在哪一步。

阶段 1:把日志集中起来(Loki)

第一根补上的柱子是日志。原因很简单:当指标指向异常之后,大家的第一反应永远是去翻日志。

别小看"集中"这两个字。如果日志还散在各台机器的 /var/log 里,出了事就得挨个 SSH,跨实例还拼不起来时间线。集中到 Loki 之后,Grafana 里就能和指标放在同一块屏上看。

选 Loki 而不是 ELK 的理由也很实际:Loki 不对日志内容建全文索引,只索引标签,存储成本比 ES 低一个量级,正好和已有的 Grafana 复用。代价是全文检索没 ES 那么强,但对"按 svc、按时间、按 trace_id 捞一段日志"这种最常见的场景,完全够用。

⚠️ 注意:别重新设计一套日志标签。 Loki 也是靠标签组织数据的,svc、type、env 这套命名要和第 2 篇对齐,否则指标和日志永远串不到一起。

触发信号: 排查一个问题需要登录 3 台以上机器捞日志;或者需要跨实例对齐时间线。

阶段 2:补上链路追踪(Tempo / Jaeger)+ Exemplar

第二根柱子是链路追踪。解决的是分布式系统里最难受的一个问题:一个请求经过网关、应用 A、应用 B、数据库,到底慢在哪一跳。

这里有个能立刻提升体验的巧劲:Exemplar(示例)。它能在指标曲线上挂一个点,点开直接跳到对应的那条 trace。相当于从"指标发现异常"一步跨到"链路看到现场",中间不用再人肉找时间戳。

用法大致是这样:应用侧(Micrometer 从 1.12 起支持)在打点直方图时,把当前的 trace_id 作为 exemplar 塞进去;查询时在 PromQL 里加上 exemplars,Grafana 面板上就会出现可点击的点:

# 在 P95 延迟曲线上叠加 exemplar,点开即跳 Tempo
histogram_quantile(
  0.95,
  sum by (le, svc) (rate(http_server_requests_seconds_bucket[5m]))
)
# 应用侧开启 exemplar(Micrometer + Prometheus registry)
management:
  metrics:
    distribution:
      percentiles-histogram:
        http.server.requests: true   # 要直方图才有桶,才能挂 exemplar

⚠️ 注意:这里要翻回第 4 篇和第 12 篇的老账。开 percentiles-histogram 会让指标基数暴涨,直方图一开,账立刻变成另一个量级(第 12 篇那张算账表里,90,000 序列 / 1 GB 每天就是这么来的)。所以 exemplar 不是所有接口都开,挑核心入口接口开就够;否则还没吃到可观测性的红利,先把 Prometheus 撑爆了。

触发信号: 一次调用跨了多个服务,光看指标定位不到慢在哪一跳。

阶段 3:统一采集与语义(OpenTelemetry)

到了这一步,就会发现一个新麻烦:指标一套 SDK、日志一套 agent、链路一套 SDK,三套东西各自定义标签、各自上报,配起来又碎又容易不一致。

OpenTelemetry(OTel)就是用一套规范 + 一个 Collector,把 metrics / logs / traces 三路信号收进来,再分别导出到 Prometheus、Loki、Tempo。数据源头带上统一的 service.name、trace_id 这类上下文,三根柱子天然就能对上。

一个最小可用的 Collector 配置长这样:

# otel-collector-config.yml
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

processors:
  batch:
  resource:
    attributes:
      - key: env
        value: prod
        action: upsert

exporters:
  prometheusremotewrite:
    endpoint: http://prometheus:9090/api/v1/write
  otlp/tempo:
    endpoint: tempo:4317
    tls:
      insecure: true
  loki:
    endpoint: http://loki:3100/loki/api/v1/push

service:
  pipelines:
    metrics:
      receivers: [otlp]
      processors: [resource, batch]
      exporters: [prometheusremotewrite]
    traces:
      receivers: [otlp]
      processors: [resource, batch]
      exporters: [otlp/tempo]
    logs:
      receivers: [otlp]
      processors: [resource, batch]
      exporters: [loki]

prometheusremotewrite 那个 exporter 正好接的是第 12 篇讲过的 remote_write 接口。

⚠️ 注意:别一上来就"OTel 改造全公司"。 存量应用改用 OTel SDK 是实打实的代码改造,成本不小。务实的做法是:新项目直接上 OTel;老项目先只用 Collector 收 OTLP 做聚合转发,SDK 慢慢换。演进是加法,不是革命。

阶段 4:统一查询与关联(Grafana 一个入口)

三根柱子都有了后,最后一步是让人别再自己来回切工具。

Grafana 早就不只是画指标了,它现在可以同时接 Prometheus、Loki、Tempo 作为数据源,并且支持三向跳转:

  • 指标面板发现异常 → 点 exemplar 跳到 Tempo 看链路;
  • 链路的某个 span 慢 → 从 span 上直接跳 Loki 看那段日志;
  • 日志里出现某个 trace_id → 反过来定位到具体那次 trace。

数据源之间的关联,靠的是一个统一的标注(Grafana 里的 "Data links" 或 derivied fields):

# 让日志里的 trace_id 变成可点击链接
字段:trace_id
链接:http://tempo:3000/explore?query=${__value.raw}

到这一步,"从告警到根因的跳转"才真正闭环:告警通知里附一个链接,值班的人点开就是现场,而不是从零开始查。

五、按团队规模,选一条务实的路线

仅供参考:

团队规模 / 系统复杂度建议停在理由
个人 / 中小企业,系统简单阶段 0~1指标 + 集中日志已覆盖 90% 场景,别过度设计
中型团队,服务 10+,有分布式调用阶段 0~2链路追踪是定位跨服务慢问题的刚需
大型 / 云原生 / 多团队阶段 0~4三支柱 + OTel + 统一入口,才能撑住规模和协作

⚠️ 一句话:可观测性是有成本的,而且是持续成本。 Loki、Tempo 都要存数据、都要运维,第 12 篇那笔存储账一条都跑不掉。为了"显得先进"而上一堆组件,最后只会多养几套需要被监控的系统。 选择永远应该由痛点决定,而不是由名词决定。

六、演进路上最容易踩的几个坑

  1. 为了可观测性而上可观测性。 团队里指标还没理清楚,就急着上三支柱。结果三套数据、三套标签、三套告警,比原来更乱。先把阶段 0 的地基(标签规范、闭环、减法)做扎实,再谈演进。
  2. 标签/上下文不统一。 三根柱子能不能串起来,全看 svc、type、trace_id 这些共同上下文有没有对齐。这跟第 9、10 篇里"标签规范是隐藏地基"是同一个道理,柱子越多,地基不牢的代价越大。
  3. exemplar + 直方图一起用力过猛。 第 4、12 篇的基数坑会在这里集中爆发。所有接口无脑开直方图 + exemplar,Prometheus 内存和磁盘先扛不住。
  4. 把新平台变成新的故障源。 "监控的价值是早知道,但前提是它自己没有变成新的故障源",在可观测性阶段同样成立。采集、存储、查询组件都要独立部署、独立监控,别让它们和业务抢资源。
  5. 忘了数据保留与成本。 日志和链路的体量比指标大得多,上线第一天就要定好保留策略和采样策略(比如链路按比例采样、日志分级保留)。

七、小结

至此,整个 Prometheus 系列十四篇就正式收尾了。回望一遍:

前 13 篇把"能采集、能看、能告警、能出报告、扛得住、守得住"这套监控体系完整建了起来;本篇则把它当成一个整体重新审视,并指向了下一步。

本篇核心要点:

  • 体系是闭环,不是清单。 采集 → 方法收敛 → 告警响应 → 可视化呈现 → 决策改进 → 回头优化采集,环转起来才有价值;只堆采集和告警,等于只建了闭环的一条边。
  • 六条地基要进规范。 标签规范、闭环思维、先做减法、阈值贴业务、独立部署、默认即不安全。
  • 监控 ≠ 可观测性。 监控回答"已知的已知",可观测性回答"未知的未知";指标是可观测性里性价比最高的一根柱子,但只有一根柱子撑不起"可观测"三个字。
  • 演进要痛点驱动、分阶段走。 指标(阶段 0)→ 日志 Loki(1)→ 链路 Tempo + Exemplar(2)→ 统一采集 OTel(3)→ 统一查询关联(4)。每一步都先问"是不是真被卡住了",卡住再上。
  • OTel 与新体系不是推倒重来。 通过 remote_write 写回已有的 Prometheus,老资产全部保留,这才是平滑演进的正确姿势。
  • 规模和成本要匹配。 个人 / 中小企业停在阶段 0~1 就够了;可观测性是持续成本,别让"先进"变成负担。

最后一句:

监控不是一次性的配置工作,而是一项需要持续打磨的基础设施。前面十三篇教会你"怎么把它建起来",本篇希望帮你"知道它建成了什么样、以及该往哪长"。工具会迭代,名词会更新,但"让数据服务于决策"这件事,不会变。