三大支柱

可观测性(Observability)通常由三类数据构成(前文提到过,这里展开"端到端"的视角):

一、指标(Metrics)

聚合的数值时间序列——如 QPS、延迟的 P99、错误率、CPU 使用率。

  • 优点:存储成本低、查询快、适合告警和仪表板;
  • 缺点:丢失了个体信息——你无法知道"是哪些请求慢"。

二、日志(Logs)

离散的事件记录——带时间戳、上下文、和任意的文本/结构化内容。

  • 优点:信息详细,能定位到具体的事件;
  • 缺点:量大、成本高,且单独的日志条目难以串联成故事。

三、追踪(Traces)

这是"端到端"的关键。

分布式追踪(Distributed Tracing):记录一个请求在分布式系统中流经的全部服务,形成一棵调用树。

端到端的含义

一个请求从"用户点击"到"数据库返回",可能经过:

浏览器 → CDN → 负载均衡 → API 网关 → 用户服务 → 认证服务
                                   → 订单服务 → 数据库
                                   → 推荐服务 → 缓存
                                   → 支付服务 → 第三方 API

"端到端"意味着:能看到这个请求在每一跳的耗时和状态,从浏览器一直到数据库。

没有端到端追踪时,你看到的是:

  • 网关说"平均延迟 200ms";
  • 订单服务说"我很快";
  • 数据库说"我很快";
  • 但用户说"很慢"。

有了端到端追踪,你能看到:

  • 这个特定请求总共 3.2 秒;
  • 其中订单服务花了 2.8 秒;
  • 订单服务内部的 2.8 秒里,有 2.7 秒在等数据库的某个慢查询;
  • 该慢查询是因为缺少索引。

问题定位从"猜测"变成了"直指"。

核心概念

一、Trace 与 Span

Trace:一个请求的完整链路(一棵树)。

Span:链路中的一个操作单元(如一次 HTTP 调用、一次数据库查询、一个函数调用)。

Span 包含:

  • 操作名称;
  • 开始时间和持续时间;
  • 父子关系(谁调用了我);
  • 属性/标签(如 HTTP 方法、状态码、SQL 语句、用户 ID);
  • 事件(Span 内发生的离散事件);
  • 状态(成功/失败)。

Trace ID:贯穿整个链路的唯一标识。

二、上下文传播(Context Propagation)

这是分布式追踪的技术核心。

当一个服务调用另一个服务时,必须把 Trace ID 和 Span ID 传递过去——通常通过 HTTP 请求头。

标准:W3C Trace Context(traceparent 头)已成为跨系统的标准。之前的方案有 B3(Zipkin)、Jaeger 的格式等。

如果传播中断(如某个服务没有传递头部),追踪链路就会断裂——这是实际部署中最常见的问题之一。

因此:需要尽可能早地、广泛地植入自动埋点(instrumentation),并对关键路径做手工确认。

三、采样(Sampling)

对每一个请求都记录完整的追踪,成本过高。因此需要采样:

头部采样(Head Sampling):在请求入口决定"是否记录"——简单,但可能漏掉罕见但重要的慢请求。

尾部采样(Tail Sampling):先记录,等链路完成后再决定"是否保留"。

优势:可以保留所有的错误请求和慢请求(这才是最需要看的),而丢弃大部分正常的快速请求。

代价:需要在收集端做缓冲和决策,架构更复杂。

这是生产环境中推荐的做法——因为你最需要的正是那些"异常"的请求。

标准与工具

OpenTelemetry(OTel)

这是当前最重要的行业标准。

OpenTelemetry 由 OpenTracing 和 OpenCensus 合并而成(2019 年),是 CNCF 的毕业项目。

它统一了:

  • API 和 SDK:应用如何产生遥测数据;
  • OTLP 协议:数据如何传输;
  • 语义约定(Semantic Conventions):统一的字段命名(如 http.method、db.system)——这使得不同系统产生的数据可以互相理解。

关键价值:

厂商中立。你可以用 OTel 埋点,然后把数据发送到任何后端(Jaeger、Zipkin、商业 APM、云厂商服务)——而不被锁定。

这结束了"每家 APM 厂商一套私有埋点 SDK"的局面。

工具:

  • Jaeger:Uber 开源的分布式追踪系统;
  • Zipkin:Twitter 开源;
  • Grafana Tempo:与 Grafana / Prometheus / Loki 生态整合;
  • 商业 APM:Datadog、New Relic、Dynatrace 等。

从"监控"到"可观测性"

这是一个重要的观念转变:

传统监控:预先定义你知道要问的问题("QPS 是多少?错误率是多少?")——依赖预设的仪表板和告警规则。

可观测性:系统保留了足够丰富的、有结构的原始数据,使得你能够问出事先没想到的问题。

这就是为什么"高基数(High Cardinality)"字段很重要:

  • 如果你记录了 user_id、tenant_id、request_id、feature_flag 等维度;
  • 那么当一个问题发生时,你可以临时按任意维度切分和筛选——"是不是只有某个租户的请求慢?是不是只有开了某个功能开关的用户受影响?"

如果你的指标只有聚合值(没有维度),这些问题就问不了。

与其它实践的结合

一、与 SLO 结合

基于错误预算的告警(前文提到过)需要可靠的指标——可观测性提供了基础。

二、与事件响应结合

在事故发生时,追踪数据能大幅缩短定位时间(MTTD/MTTR)。

三、与持续剖析(Continuous Profiling)结合

这是"第四支柱"的说法:持续采集 CPU / 内存剖析数据。

价值:当发现"某个服务慢"时,剖析数据能告诉你是哪一行代码消耗的——把"服务慢"精确到"函数慢"。

四、与前端结合(真正的"端到端")

真正的端到端应该包括浏览器端:

  • 页面加载性能(Core Web Vitals);
  • 前端的错误和慢交互;
  • 前端发起的 API 调用的耗时。

这被称为 RUM(Real User Monitoring,真实用户监控)。

意义:很多时候"慢"发生在前端(渲染、JS 执行、网络条件差),而后端指标完全正常。

只有把前端纳入可观测性,才能说是真正的"端到端"。

实践的困难

一、埋点覆盖不全

自动化埋点(auto-instrumentation)能覆盖主流框架,但:

  • 自定义的异步处理、消息队列、批处理任务常常缺失;
  • 需要手工补充。

二、成本

全量追踪的数据量极大——需要在采样、保留期、存储之间做权衡。

三、标准化的执行

即使有 OTel,团队内部仍需要就"记录什么字段""如何命名"达成约定——否则数据仍然难以关联。

四、不等于"有了工具就等于可观测"

工具只是手段。真正的可观测性,是指团队能用这些数据快速回答问题——这需要在实践中反复演练。

说明:本文为可观测性工程的知识整理。