凌晨 3 点,你的手机响了。告警系统显示 P99 延迟从 200ms 飙升到 2s,但 CPU 使用率正常、内存正常、磁盘 I/O 正常。你打开 Grafana 面板,看到一条红色的曲线在飙升,但你不知道为什么。
这就是传统监控的困境:它告诉你系统出了问题,但无法帮你理解为什么。
可观测性(Observability)不是监控的升级版,而是一种根本不同的思维方式。监控是”我知道会出什么问题,所以我提前设防”;可观测性是”我不知道会出什么问题,所以我需要系统能让我提问”。
本章是整个系列的认知基础。建立可观测性的思维模型,理解三大信号(日志、指标、追踪)各自的定位与局限,并引入可观测性成熟度模型——帮助你评估团队当前的可观测性水平,以及下一步该往哪里走。
一、监控与可观测性:根本区别
1.1 监控的哲学:已知未知
传统监控建立在预知故障模式的假设上。你基于过去的经验,预设一系列条件判断:
- CPU 使用率 > 80% → 告警
- 内存使用率 > 90% → 告警
- HTTP 5xx 比例 > 1% → 告警
这种方式在单体架构下非常有效——系统复杂度有限,故障模式相对固定。但在微服务架构下,它面临三个根本挑战:
- 未知未知:你无法为从未见过的故障模式预设告警规则
- 组合爆炸:500 个微服务之间的交互路径远超人力所能枚举
- 症状 vs 根因:CPU 高是症状,不是根因——根因可能是某个下游服务变慢导致的重试风暴
1.2 可观测性的哲学:未知未知
可观测性一词来自控制论。一个系统是”可观测的”,意味着你可以从外部输出推断出内部状态——而不需要预先知道内部状态会怎样变化。
可观测性(Observability)源自控制论,由 Rudolf E. Kálmán 于 1960 年提出。在控制论中,一个系统是可观测的,当且仅当从外部输出可以唯一确定内部状态。这个定义强调的是推断能力,而非预设能力。
在软件工程中,可观测性意味着:
- 你不需要预先知道会出什么问题
- 你可以在运行时提出任意问题
- 问题的答案来自系统本身产生的数据,而非你预设的检查项
1.3 核心区别对比
| 维度 | 监控 | 可观测性 |
|---|---|---|
| 哲学 | 已知未知 | 未知未知 |
| 方法 | 预设检查项 | 运行时提问 |
| 数据 | 指标为主 | 日志 + 指标 + 追踪 + 性能分析 |
| 查询 | 固定面板 + 告警 | 交互式探索 |
| 故障响应 | ”系统出了什么问题?" | "系统为什么会这样?“ |
| 适用场景 | 已知故障模式 | 未知故障模式 |
| 典型工具 | Nagios、Zabbix | Honeycomb、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 延迟飙升:
监控方式:
- 看到 P99 延迟告警
- 查看 CPU/内存面板 → 正常
- 查看下游服务面板 → 某个服务延迟也高
- 登录那个服务的机器 → 看日志 → 找到错误
- 发现是数据库连接池耗尽
可观测性方式:
- 看到 P99 延迟告警
- 点击 Exemplar,直接跳转到对应的追踪链路
- 追踪链路显示请求在数据库查询 Span 卡了 1.8s
- 点击该 Span,查看关联的日志,发现
connection pool exhausted - 查看关联的指标,发现连接池使用率在过去 1 小时持续上升
区别在于:监控需要你在多个工具之间手动跳转和关联,而可观测性让数据之间的关联成为一等公民。
二、三大信号:日志、指标、追踪
可观测性的数据基础是三大信号(Three Pillars)。它们各自有不同的特征、成本和适用场景。
2.1 信号特征对比
| 特征 | 日志 | 指标 | 追踪 |
|---|---|---|---|
| 粒度 | 事件级 | 聚合级 | 请求级 |
| 基数 | 高(每条日志唯一) | 低(标签组合有限) | 中(每条追踪唯一但可采样) |
| 成本 | 高(存储 + 索引) | 低(预聚合) | 中(可采样控制) |
| 擅长的 | 排查具体错误 | 发现趋势异常 | 定位瓶颈服务 |
| 不擅长的 | 趋势分析、聚合 | 具体事件还原 | 聚合统计 |
| 典型查询 | ”这个请求为什么失败了?" | "P99 延迟是多少?" | "请求在哪个服务卡住了?“ |
| 典型工具 | Loki、Elasticsearch | Prometheus、VictoriaMetrics | Tempo、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 日志。
日志成本是可观测性支出中最大的单项。在规划可观测性平台时,务必先做日志分级策略: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 和 Histogramfunc 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 三大信号的协同
三大信号不是孤岛,它们需要协同工作:
这种协同不是自动发生的——它需要你在架构层面设计信号关联机制。在第 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 三层认知模型
可观测性的价值体现在三个认知层次:
| 认知层次 | 核心问题 | 主要信号 | 典型工具 |
|---|---|---|---|
| 检测 | 系统出了什么问题? | 指标 | Prometheus + Grafana |
| 定位 | 问题在哪里? | 追踪 | Tempo + Jaeger |
| 理解 | 为什么会这样? | 日志 + 性能分析 | Loki + Pyroscope |
大多数团队停留在第一层——他们能检测到问题,但无法快速定位和理解根因。可观测性工程的目标是让团队在三个层次上都具备高效的能力。
4.2 可观测性 vs 调试
可观测性不是调试的替代品,而是调试的前置条件:
| 维度 | 可观测性 | 调试 |
|---|---|---|
| 时机 | 生产环境,实时 | 开发/测试环境,按需 |
| 方式 | 非侵入式观测 | 侵入式断点/日志 |
| 范围 | 全系统 | 单进程/单服务 |
| 目标 | 理解系统行为 | 修复具体 Bug |
| 成本 | 持续的(但可控) | 按需的(但可能影响生产) |
好的可观测性让你减少调试的需要——因为你可以从可观测性数据中推断出根因,而不需要在生产环境中附加调试器。
五、可观测性成熟度模型
5.1 五级成熟度
基于行业实践,可以将可观测性成熟度分为五个等级:
5.2 各级别详细特征
| 级别 | 名称 | 特征 | 典型工具 | MTTD | MTTR |
|---|---|---|---|---|---|
| Level 1 | 被动响应 | 靠用户反馈发现问题,无系统化监控 | 无 / 邮件 | 数小时~数天 | 数小时~数天 |
| Level 2 | 基础监控 | CPU/内存/磁盘/网络告警,固定面板 | Nagios、Zabbix | 数分钟~数小时 | 数十分钟~数小时 |
| Level 3 | 信号关联 | 日志/指标/追踪联动,交互式探索 | Grafana + OTel | 数分钟 | 数分钟~数十分钟 |
| Level 4 | SLO 驱动 | 错误预算、燃烧率告警、多窗口检测 | 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:
- 你是否能自动检测异常(无需预设规则)?
- 你是否能自动推荐根因?
大多数团队处于 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 现代可观测性技术栈
7.2 技术选型参考
| 信号 | 推荐方案 | 备选方案 | 选型考虑 |
|---|---|---|---|
| 指标 | Prometheus + VictoriaMetrics | Mimir | VM 更易运维,Mimir 更适合超大规模 |
| 追踪 | Tempo | Jaeger | Tempo 与 Grafana 生态集成更好 |
| 日志 | Loki | Elasticsearch | Loki 成本更低,ES 搜索更灵活 |
| 性能分析 | Pyroscope | Parca | Pyroscope 与 Grafana 生态集成更好 |
| 采集 | OTel Collector | Vector | OTel 是标准,Vector 更灵活 |
| 可视化 | Grafana | Datadog | Grafana 开源,Datadog 商业化更完善 |
技术选型不是一成不变的。本系列的推荐基于 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 个月)
- 定义核心 SLO
- 建立错误预算和燃烧率告警
- 详见第 11 章:SLO 与告警
阶段 4:持续性能分析(1-2 个月)
- 部署 Pyroscope/Parca
- 在 Grafana 中集成火焰图
- 详见第 6 章:持续性能分析
阶段 5:平台化(3-6 个月)
- 多租户、权限、数据生命周期
- 详见第 13 章:可观测性平台设计
8.2 投资回报分析
| 阶段 | 投入 | 回报 | ROI |
|---|---|---|---|
| 补齐信号 | 2 人月 | MTTR 降低 50% | 高 |
| 信号关联 | 3 人月 | 排障时间从小时级降到分钟级 | 高 |
| SLO 驱动 | 2 人月 | 告警数量减少 80%,误报率降低 | 中 |
| 持续性能分析 | 1 人月 | 性能问题发现时间从天级降到小时级 | 中 |
| 平台化 | 5 人月 | 多团队自助式使用,运维成本降低 | 长期 |
九、动手实践:验证你的可观测性环境
9.1 启动 Docker 环境
# 使用系列提供的 Docker Compose 环境cd observability-labdocker compose up -d
# 验证所有组件docker compose ps9.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 中验证
# 打开 Grafanaopen 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 是北极星。 | 工程原则 |
支持与分享
如果这篇文章对你有帮助,欢迎支持作者或分享给更多人
部分信息可能已经过时






