mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
4550 字
12 分钟
可观测性全景:从监控到可观测性
2025-07-05

凌晨 3 点,你的手机响了。告警系统显示 P99 延迟从 200ms 飙升到 2s,但 CPU 使用率正常、内存正常、磁盘 I/O 正常。你打开 Grafana 面板,看到一条红色的曲线在飙升,但你不知道为什么。

这就是传统监控的困境:它告诉你系统出了问题,但无法帮你理解为什么

可观测性(Observability)不是监控的升级版,而是一种根本不同的思维方式。监控是”我知道会出什么问题,所以我提前设防”;可观测性是”我不知道会出什么问题,所以我需要系统能让我提问”。

本章是整个系列的认知基础。建立可观测性的思维模型,理解三大信号(日志、指标、追踪)各自的定位与局限,并引入可观测性成熟度模型——帮助你评估团队当前的可观测性水平,以及下一步该往哪里走。

一、监控与可观测性:根本区别#

1.1 监控的哲学:已知未知#

传统监控建立在预知故障模式的假设上。你基于过去的经验,预设一系列条件判断:

  • CPU 使用率 > 80% → 告警
  • 内存使用率 > 90% → 告警
  • HTTP 5xx 比例 > 1% → 告警

这种方式在单体架构下非常有效——系统复杂度有限,故障模式相对固定。但在微服务架构下,它面临三个根本挑战:

  1. 未知未知:你无法为从未见过的故障模式预设告警规则
  2. 组合爆炸:500 个微服务之间的交互路径远超人力所能枚举
  3. 症状 vs 根因:CPU 高是症状,不是根因——根因可能是某个下游服务变慢导致的重试风暴

1.2 可观测性的哲学:未知未知#

可观测性一词来自控制论。一个系统是”可观测的”,意味着你可以从外部输出推断出内部状态——而不需要预先知道内部状态会怎样变化。

Note

可观测性(Observability)源自控制论,由 Rudolf E. Kálmán 于 1960 年提出。在控制论中,一个系统是可观测的,当且仅当从外部输出可以唯一确定内部状态。这个定义强调的是推断能力,而非预设能力

在软件工程中,可观测性意味着:

  • 你不需要预先知道会出什么问题
  • 你可以在运行时提出任意问题
  • 问题的答案来自系统本身产生的数据,而非你预设的检查项

1.3 核心区别对比#

维度监控可观测性
哲学已知未知未知未知
方法预设检查项运行时提问
数据指标为主日志 + 指标 + 追踪 + 性能分析
查询固定面板 + 告警交互式探索
故障响应”系统出了什么问题?""系统为什么会这样?“
适用场景已知故障模式未知故障模式
典型工具Nagios、ZabbixHoneycomb、Grafana Tempo
成熟度标志告警覆盖率平均检测时间(MTTD)

1.4 一个具体例子#

# 传统监控:只知道"出错了"
curl -s http://api.example.com/health
# → HTTP 500
# 可观测性:知道"为什么出错了"
# 1. 指标:P99 延迟从 50ms 飙升到 2s
# 2. 追踪:发现 DB 查询耗时 1.8s
# 3. 日志:日志显示 "connection pool exhausted, waiting for connection"
# → 根因:连接池配置过小,高并发时耗尽

假设你的 API 网关 P99 延迟飙升:

监控方式

  1. 看到 P99 延迟告警
  2. 查看 CPU/内存面板 → 正常
  3. 查看下游服务面板 → 某个服务延迟也高
  4. 登录那个服务的机器 → 看日志 → 找到错误
  5. 发现是数据库连接池耗尽

可观测性方式

  1. 看到 P99 延迟告警
  2. 点击 Exemplar,直接跳转到对应的追踪链路
  3. 追踪链路显示请求在数据库查询 Span 卡了 1.8s
  4. 点击该 Span,查看关联的日志,发现 connection pool exhausted
  5. 查看关联的指标,发现连接池使用率在过去 1 小时持续上升

区别在于:监控需要你在多个工具之间手动跳转和关联,而可观测性让数据之间的关联成为一等公民。

二、三大信号:日志、指标、追踪#

可观测性的数据基础是三大信号(Three Pillars)。它们各自有不同的特征、成本和适用场景。

2.1 信号特征对比#

graph TB subgraph 三大信号 LOG[" 日志<br/>事件粒度<br/>高基数<br/>高成本"] METRIC[" 指标<br/>聚合粒度<br/>低基数<br/>低成本"] TRACE[" 追踪<br/>请求粒度<br/>中基数<br/>中成本"] end LOG -->|"TraceID 关联"| TRACE METRIC -->|"Exemplar 关联"| TRACE LOG -->|"指标日志"| METRIC style LOG fill:#e3f2fd,stroke:#1565c0 style METRIC fill:#e8f5e9,stroke:#2e7d32 style TRACE fill:#fff3e0,stroke:#e65100
特征日志指标追踪
粒度事件级聚合级请求级
基数高(每条日志唯一)低(标签组合有限)中(每条追踪唯一但可采样)
成本高(存储 + 索引)低(预聚合)中(可采样控制)
擅长的排查具体错误发现趋势异常定位瓶颈服务
不擅长的趋势分析、聚合具体事件还原聚合统计
典型查询”这个请求为什么失败了?""P99 延迟是多少?""请求在哪个服务卡住了?“
典型工具Loki、ElasticsearchPrometheus、VictoriaMetricsTempo、Jaeger

2.2 日志:事件级真相#

日志是系统行为的逐事件记录。每条日志记录一个离散事件,包含时间戳、消息和上下文信息。

// 非结构化日志 — 难以搜索和分析
2026-06-18 03:14:22 ERROR Failed to process request for user 12345
// 结构化日志 — 可搜索、可分析、可关联
{
"timestamp": "2026-06-18T03:14:22.456Z",
"level": "ERROR",
"message": "Failed to process request",
"service": "order-service",
"trace_id": "abc123def456",
"span_id": "789ghi",
"user_id": "12345",
"error_code": "DB_CONNECTION_TIMEOUT",
"duration_ms": 5000
}

日志的核心价值在于保真度——它记录了系统行为的完整细节。但代价是高成本:一个中等规模的微服务集群每天可能产生数 TB 日志。

Warning

日志成本是可观测性支出中最大的单项。在规划可观测性平台时,务必先做日志分级策略:ERROR 级别全量保留、INFO 级别采样保留、DEBUG 级别按需开启。详见第 2 章:结构化日志

2.3 指标:聚合级趋势#

指标是系统状态的数值度量,按时间序列组织。每个指标由名称、一组标签(labels)和一个数值组成。

# 查询过去 5 分钟的 P99 延迟
histogram_quantile(0.99,
sum(rate(http_request_duration_seconds_bucket[5m])) by (le, service)
)
# 查询错误率
sum(rate(http_requests_total{status=~"5.."}[5m]))
/
sum(rate(http_requests_total[5m]))

指标的核心价值在于低成本 + 高查询效率。通过预聚合,你可以在秒级查询数百万时间序列的趋势。但代价是信息丢失——你无法从 P99 延迟还原出具体是哪个请求慢。

使用 OpenTelemetry SDK 可以方便地创建和记录指标:

// 使用 OTel SDK 创建 Counter 和 Histogram
func initMetrics(meter metric.Meter) {
// 请求计数器
requestCounter, _ := meter.Int64Counter("http_requests_total",
metric.WithDescription("HTTP 请求总数"),
)
// 请求延迟直方图
latencyHist, _ := meter.Float64Histogram("http_request_duration_seconds",
metric.WithDescription("HTTP 请求延迟"),
)
// 记录指标
requestCounter.Add(ctx, 1, metric.WithAttributes(
attribute.String("method", "GET"),
attribute.Int("status", 200),
))
latencyHist.Record(ctx, 0.15, metric.WithAttributes(
attribute.String("method", "GET"),
))
}

2.4 追踪:请求级旅程#

追踪记录一个请求在分布式系统中的完整路径。每个追踪由多个 Span 组成,每个 Span 代表一个操作单元。

{
"trace_id": "abc123def456",
"spans": [
{
"span_id": "span1",
"operation": "API Gateway",
"duration_ms": 2000,
"children": [
{
"span_id": "span2",
"operation": "order-service.process",
"duration_ms": 1800,
"children": [
{
"span_id": "span3",
"operation": "db.query",
"duration_ms": 1700
}
]
}
]
}
]
}

追踪的核心价值在于因果链——它不仅告诉你”哪里慢”,还告诉你”为什么慢”(因为下游的下游的数据库查询慢)。但代价是高基数 + 高成本——每个请求产生一条追踪,需要采样策略控制成本。

2.5 三大信号的协同#

三大信号不是孤岛,它们需要协同工作:

sequenceDiagram participant M as 指标 participant T as 追踪 participant L as 日志 Note over M: P99 延迟飙升 M->>T: Exemplar: 点击跳转到慢请求追踪 Note over T: 定位到 db.query Span T->>L: TraceID 过滤: 查看该请求的所有日志 Note over L: 发现 connection pool exhausted L->>M: 错误码维度: 查看该错误的趋势 Note over M: 确认是渐进式上升

这种协同不是自动发生的——它需要你在架构层面设计信号关联机制。在第 10 章:信号关联中深入讨论。

三、第四大支柱:持续性能分析#

近年来,持续性能分析(Continuous Profiling)被越来越多地认为是可观测性的”第四大支柱”。

3.1 为什么需要性能分析?#

三大信号回答了”系统出了什么问题”和”问题在哪里”,但无法回答”代码为什么慢”:

  • 指标告诉你 CPU 使用率 80%,但不知道是哪个函数在消耗 CPU
  • 追踪告诉你请求在某个服务卡了 2s,但不知道是哪个函数调用链导致的
  • 日志告诉你发生了错误,但不知道错误发生时的调用栈

持续性能分析填补了这个空白——它持续采集程序的 CPU/内存/锁竞争等性能数据,生成火焰图,让你看到代码级别的性能热点。

3.2 火焰图:性能分析的第一工具#

火焰图(Flame Graph)由 Brendan Gregg 发明,是性能分析最直观的可视化方式:

  • X 轴:函数调用栈的宽度代表采样命中次数(不是时间)
  • Y 轴:调用栈深度(底部是入口函数,顶部是叶子函数)
  • 颜色:通常无特殊含义,仅用于区分不同函数
┌──────────┐
│ func_d() │
┌───┴──────────┴───┐
│ func_b() │
┌───┴──────────────────┴───┐
│ func_a() │
┌───┴──────────────────────────┴───┐
│ main() │
└──────────────────────────────────┘

第 6 章:持续性能分析中深入讨论火焰图的原理与工具。

四、可观测性认知模型#

4.1 三层认知模型#

可观测性的价值体现在三个认知层次:

graph TB subgraph 认知层次 L1[" 第一层:检测<br/>系统出了什么问题?"] L2[" 第二层:定位<br/>问题在哪里?"] L3[" 第三层:理解<br/>为什么会这样?"] end L1 --> L2 --> L3 L1 -.- M["指标"] L2 -.- T["追踪"] L3 -.- LOG["日志 + 性能分析"] style L1 fill:#e3f2fd,stroke:#1565c0 style L2 fill:#fff3e0,stroke:#e65100 style L3 fill:#e8f5e9,stroke:#2e7d32
认知层次核心问题主要信号典型工具
检测系统出了什么问题?指标Prometheus + Grafana
定位问题在哪里?追踪Tempo + Jaeger
理解为什么会这样?日志 + 性能分析Loki + Pyroscope

大多数团队停留在第一层——他们能检测到问题,但无法快速定位和理解根因。可观测性工程的目标是让团队在三个层次上都具备高效的能力。

4.2 可观测性 vs 调试#

可观测性不是调试的替代品,而是调试的前置条件:

维度可观测性调试
时机生产环境,实时开发/测试环境,按需
方式非侵入式观测侵入式断点/日志
范围全系统单进程/单服务
目标理解系统行为修复具体 Bug
成本持续的(但可控)按需的(但可能影响生产)

好的可观测性让你减少调试的需要——因为你可以从可观测性数据中推断出根因,而不需要在生产环境中附加调试器。

五、可观测性成熟度模型#

5.1 五级成熟度#

基于行业实践,可以将可观测性成熟度分为五个等级:

graph LR L1["Level 1<br/> 被动响应<br/>靠用户反馈发现问题"] --> L2["Level 2<br/> 基础监控<br/>CPU/内存/磁盘告警"] L2 --> L3["Level 3<br/> 信号关联<br/>日志/指标/追踪联动"] L3 --> L4["Level 4<br/> SLO 驱动<br/>错误预算与燃烧率"] L4 --> L5["Level 5<br/> 主动预防<br/>异常检测与自动根因"] style L1 fill:#ffcdd2,stroke:#c62828 style L2 fill:#ffe0b2,stroke:#e65100 style L3 fill:#fff9c4,stroke:#f9a825 style L4 fill:#c8e6c9,stroke:#2e7d32 style L5 fill:#bbdefb,stroke:#1565c0

5.2 各级别详细特征#

级别名称特征典型工具MTTDMTTR
Level 1被动响应靠用户反馈发现问题,无系统化监控无 / 邮件数小时~数天数小时~数天
Level 2基础监控CPU/内存/磁盘/网络告警,固定面板Nagios、Zabbix数分钟~数小时数十分钟~数小时
Level 3信号关联日志/指标/追踪联动,交互式探索Grafana + OTel数分钟数分钟~数十分钟
Level 4SLO 驱动错误预算、燃烧率告警、多窗口检测Grafana SLO数分钟数分钟
Level 5主动预防异常检测、自动根因分析、自愈ML + 自动化秒级~分钟级分钟级

5.3 如何评估你的团队#

回答以下问题,评估你的团队处于哪个级别:

Level 1 → Level 2

  • 你是否有自动化的基础设施监控?
  • 你是否能在用户报告之前发现问题?

Level 2 → Level 3

  • 你是否能在 5 分钟内定位延迟飙升的根因服务?
  • 你的日志、指标、追踪是否可以关联查询?

Level 3 → Level 4

  • 你的告警是否基于 SLO 而非阈值?
  • 你是否有错误预算的概念?

Level 4 → Level 5

  • 你是否能自动检测异常(无需预设规则)?
  • 你是否能自动推荐根因?
Note

大多数团队处于 Level 2 到 Level 3 之间。从 Level 2 到 Level 3 的关键跨越是信号关联——这不仅是工具问题,更是架构问题。本系列的核心目标就是帮助你完成这个跨越。

六、可观测性的工程原则#

6.1 七大原则#

原则说明反模式
仪器化一切每个服务都应该产生日志、指标、追踪只在出问题时才加日志
结构化优先所有信号都应该是结构化的非结构化文本日志
关联是一等公民信号之间的关联应该是设计时考虑的,而非事后补救日志里没有 TraceID
SLO 是北极星可观测性的最终目的是保障 SLO告警基于任意阈值
成本与价值对齐不同信号的成本不同,采样策略应该与价值对齐所有日志全量保留
开发者体验可观测性应该是开发者的工具,而非运维的专属开发者无法访问生产可观测性数据
开放标准使用 OpenTelemetry 等开放标准,避免厂商锁定绑定特定厂商的 SDK

6.2 反模式识别#

以下是常见的可观测性反模式:

反模式 1:日志即监控

  • 症状:所有问题都要”看日志”
  • 问题:日志搜索是 O(n) 操作,在 TB 级日志中搜索效率极低
  • 解决:用指标做检测,用追踪做定位,用日志做确认

反模式 2:告警即监控

  • 症状:配置了上千条告警规则
  • 问题:告警疲劳——90% 的告警被忽略
  • 解决:SLO 驱动告警,详见第 11 章:SLO 与告警

反模式 3:面板即可观测性

  • 症状:Grafana 上有几百个面板
  • 问题:面板只能回答预设的问题,无法应对未知问题
  • 解决:交互式探索 + 信号关联

反模式 4:工具碎片化

  • 症状:日志用 ELK、指标用 Prometheus、追踪用 Jaeger、告警用 PagerDuty
  • 问题:工具之间无法关联,排障需要切换多个系统
  • 解决:统一数据采集(OTel)+ 统一可视化(Grafana)

七、可观测性技术栈全景#

7.1 现代可观测性技术栈#

graph TB subgraph 应用[" 应用层"] APP["应用服务"] SDK["OTel SDK"] end subgraph 采集[" 采集层"] OTEL["OTel Collector"] EBPF["eBPF Agent"] PROF["Profile Agent"] end subgraph 存储[" 存储层"] PROM["Prometheus<br/>VictoriaMetrics<br/>Mimir"] TEMPO["Tempo<br/>Jaeger"] LOKI["Loki<br/>Elasticsearch"] PYRO["Pyroscope<br/>Parca"] end subgraph 展示[" 展示层"] GRAFANA["Grafana"] ALERT["告警系统"] SLO["SLO 平台"] end APP --> SDK --> OTEL APP --> EBPF APP --> PROF OTEL --> PROM OTEL --> TEMPO OTEL --> LOKI EBPF --> PROM EBPF --> TEMPO PROF --> PYRO PROM --> GRAFANA TEMPO --> GRAFANA LOKI --> GRAFANA PYRO --> GRAFANA GRAFANA --> ALERT GRAFANA --> SLO style 应用 fill:#e8eaf6,stroke:#283593 style 采集 fill:#e0f2f1,stroke:#00695c style 存储 fill:#fff3e0,stroke:#e65100 style 展示 fill:#e8f5e9,stroke:#2e7d32

7.2 技术选型参考#

信号推荐方案备选方案选型考虑
指标Prometheus + VictoriaMetricsMimirVM 更易运维,Mimir 更适合超大规模
追踪TempoJaegerTempo 与 Grafana 生态集成更好
日志LokiElasticsearchLoki 成本更低,ES 搜索更灵活
性能分析PyroscopeParcaPyroscope 与 Grafana 生态集成更好
采集OTel CollectorVectorOTel 是标准,Vector 更灵活
可视化GrafanaDatadogGrafana 开源,Datadog 商业化更完善
Warning

技术选型不是一成不变的。本系列的推荐基于 2026 年的技术生态,核心原则是:优先选择开放标准(OTel),避免厂商锁定。具体工具可以替换,但标准不应该变。

八、从监控到可观测性的实践路径#

8.1 渐进式演进路线#

从监控到可观测性不是一步到位的,而是渐进式演进:

阶段 1:补齐三大信号(1-3 个月)

  • 引入 OTel SDK,为所有服务添加日志、指标、追踪
  • 部署 OTel Collector + Prometheus + Tempo + Loki
  • 在 Grafana 中建立基础面板

阶段 2:信号关联(2-4 个月)

  • 在日志中注入 TraceID
  • 在指标中添加 Exemplar
  • 在 Grafana 中配置数据源关联
  • 详见第 10 章:信号关联

阶段 3:SLO 驱动(2-3 个月)

阶段 4:持续性能分析(1-2 个月)

阶段 5:平台化(3-6 个月)

8.2 投资回报分析#

阶段投入回报ROI
补齐信号2 人月MTTR 降低 50%
信号关联3 人月排障时间从小时级降到分钟级
SLO 驱动2 人月告警数量减少 80%,误报率降低
持续性能分析1 人月性能问题发现时间从天级降到小时级
平台化5 人月多团队自助式使用,运维成本降低长期

九、动手实践:验证你的可观测性环境#

9.1 启动 Docker 环境#

# 使用系列提供的 Docker Compose 环境
cd observability-lab
docker compose up -d
# 验证所有组件
docker compose ps

9.2 发送测试数据#

# 发送一条测试追踪
curl -X POST http://localhost:4318/v1/traces \
-H "Content-Type: application/json" \
-d '{
"resourceSpans": [{
"resource": {
"attributes": [
{"key": "service.name", "value": {"stringValue": "demo-api"}},
{"key": "service.version", "value": {"stringValue": "1.0.0"}}
]
},
"scopeSpans": [{
"scope": {"name": "manual-test"},
"spans": [{
"traceId": "01234567890123456789012345678901",
"spanId": "0123456789012345",
"name": "test-request",
"kind": 1,
"startTimeUnixNano": "1700000000000000000",
"endTimeUnixNano": "1700000001000000000",
"attributes": [
{"key": "http.method", "value": {"stringValue": "GET"}},
{"key": "http.url", "value": {"stringValue": "/api/v1/orders"}}
]
}]
}]
}]
}'

9.3 在 Grafana 中验证#

# 打开 Grafana
open http://localhost:3000
# 验证步骤:
# 1. 进入 Explore 页面
# 2. 选择 Tempo 数据源
# 3. 搜索 TraceID: 01234567890123456789012345678901
# 4. 确认能看到追踪详情

9.4 验证清单#

检查项验证方式预期结果
OTel Collector 运行curl http://localhost:13133/HTTP 200
Prometheus 有数据curl http://localhost:9090/api/v1/query?query=up返回 targets
Tempo 接收追踪在 Grafana Explore 中查询能看到追踪
Loki 接收日志在 Grafana Explore 中查询能看到日志
Grafana 数据源连通在 Grafana 中测试数据源全部连通

十、本章小结#

本章建立了可观测性的认知基础:

主题核心要点关键词
监控 vs 可观测性监控是”已知未知”,可观测性是”未知未知”。监控告诉你系统出了问题,可观测性让你理解为什么。监控 vs 可观测性
三大信号日志(事件级真相)、指标(聚合级趋势)、追踪(请求级旅程)。它们各有优劣,需要协同工作。三大信号
第四大支柱持续性能分析填补了”代码为什么慢”的空白。第四大支柱
认知模型检测 → 定位 → 理解,三个层次逐步深入。认知模型
成熟度模型从被动响应到主动预防,五个级别评估团队水平。成熟度模型
工程原则仪器化一切、结构化优先、关联是一等公民、SLO 是北极星。工程原则

支持与分享

如果这篇文章对你有帮助,欢迎支持作者或分享给更多人

可观测性全景:从监控到可观测性
https://blog.souloss.com/posts/observability/observability-overview/
作者
Souloss
发布于
2025-07-05
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时