三大支柱
可观测性(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,团队内部仍需要就"记录什么字段""如何命名"达成约定——否则数据仍然难以关联。
四、不等于"有了工具就等于可观测"
工具只是手段。真正的可观测性,是指团队能用这些数据快速回答问题——这需要在实践中反复演练。
说明:本文为可观测性工程的知识整理。