Skip to content

APM

APM(Application Performance Monitoring,应用性能监控)是面向企业关键业务的实时监控、性能管理与故障定位方案。APM 系统帮助理解系统行为、定位性能问题,以便发生故障时快速恢复服务,降低 MTTR(平均修复时间)。

在单体时代,一次请求的故障通过日志栈就能定位;进入微服务后,同一请求会横跨多个服务、多个集群、多段网络,单看某一个服务的日志无法还原全貌。APM 通过标准化的信号(Signal)把"一个用户请求的经历"串联起来。

为什么需要(微服务带来的问题)

单体系统微服务系统
函数调用栈在同一个进程内调用跨进程、跨主机、跨语言
日志顺序基本可信各服务日志独立、时间戳可能漂移
定位 = 读一个应用的日志需要串联多个服务的上下文
性能瓶颈在本地可复现瓶颈可能在网络、中间件或对端服务

所以 APM 要解决的核心问题不是"采集日志",而是上下文传播(Context Propagation):把一个请求的标识(Trace ID / Span ID)从一个服务传到下一个服务,再据此把分散在各处的数据拼回一条完整链路。

Dapper:分布式追踪的奠基论文

目前主流 APM 产品(SkyWalking、Jaeger、Zipkin、Pinpoint 等)都借鉴 Google 的 Dapper 论文。Dapper 提出两个基础概念:

  • Trace(链路):一次外部请求引发的、横跨多个服务/进程的全部工作。
  • Span(跨度):Trace 中的一段操作,例如一次 RPC 调用、一次 SQL 查询、一段业务逻辑。每个 Span 记录名字、起止时间、调用方(parentSpan)、被调用方(spanId),Span 通过 ID 树状嵌套构成一个 Trace。
text
Trace = 根 Span + 若干子 Span(树状结构)
Span 关键字段:traceId, spanId, parentSpanId, operationName, startTime, duration

核心设计思想:

  • 低侵入:用字节码插桩或 RPC 框架拦截实现,尽量不改业务代码。
  • 全链路标识:通过 traceId 在进程间传递,唯一标识一次调用。
  • 采样(Sampling):全量记录成本高,通常按策略采样,用一部分请求代表整体。
  • 分析聚合:把 Spans 按 traceId 聚合、合并,重建调用链和耗时分布。

Dapper 风格 vs 统计型指标

维度Dapper 风格链路(Trace)指标(Metric)
粒度一次请求一个样本一段时间的聚合值
信息量能看单次调用完整路径只能看趋势和分布
成本高(需存储明细)低(预聚合)
定位适合钻取定位单次问题适合大盘监控

二者互为补充:先用指标发现"哪个服务 RT 异常",再用 Trace 钻取"具体是哪次请求、哪个 Span 慢"。

三大可观测信号

APM 通常把日志、指标、链路合称为可观测性三大支柱(Logs / Metrics / Traces)

信号回答的问题代表工具/标准
日志(Logs)某时刻发生了什么具体事件ELK、Loki
指标(Metrics)一段时间内整体是健康还是异常Prometheus
链路(Traces)一次请求跨服务经历了什么、慢在哪SkyWalking、Jaeger

更广义的 OpenTelemetry 还会再加入 Profile(性能剖析)等信号,但核心仍是 L/M/T 三者。

三者的关系:Trace 是骨,Metric 是肉,Log 是细节。理想做法是都带有同一个 traceId,这样从 Metric 异常 → Trace 钻取 → Log 看日志可以一键贯通。

上下文传播(Context Propagation)

要让分散的 Span 拼回一条链路,必须把追踪上下文随着调用一起传递。常见两种维度:

  1. 进程内传播:同一 JVM/进程内的调用,通过线程本地变量(ThreadLocal,SkyWalking 中叫 ContextManager)传递,不落网络报文。
  2. 跨进程传播:发起下游调用时,把 traceId / spanId / sampler 信息塞进协议头,例如 HTTP Header、gRPC Metadata、MQ 消息头。
text
服务 A                       服务 B
   │ 生成 traceId           │
   │ 写 Trace / Span 到 header  │
   ├────────────────────────►│ 读取 header,续接 Span
   │                         │ 处理,再向下游传递

常见的传播协议(Header 名以具体实现为准):

  • W3C Trace Contexttraceparent / tracestate):跨语言、跨厂商的事实标准。
  • OpenTracing 定义的注入/提取(Inject / Extract)语义。
  • SkyWalking 自有协议:通过 HTTP Header sw8、gRPC Metadata、Kafka Header 传递其二进制/文本格式上下文。

上下文传播是 APM 的正确性基础:如果 Header 名不对齐、或异步线程没传递上下文,链路就会断链、出现"孤儿 Span"。

采样(Sampling)

全量埋点会带来不小开销,且绝大多数请求不值得保存。采样策略决定"记录哪些请求":

策略说明
头部采样(Head Sampling)在 Trace 根部决定是否采样,之后整条链路一致
尾部采样(Tail Sampling)Span 全部收集后按规则决定哪些入库,更灵活但成本高
固定采样率如 10%、1%,简单但易漏掉慢请求
基于规则的采样按 URL、服务、错误状态等决定
  • 头部采样保证了一条链路要么全采要么全不采,避免"半条链路"。
  • 采样后要能看到"大约 X% 的请求被记录",否则统计会失真。
  • 错误请求通常需要强制全采,因为问题定位依赖它。

主流 APM 对比

工具侧重采样/传播语言存储
SkyWalking全栈 APM + 拓扑自有 sw8 / W3CJava、Go、Node、Py 等多语言ES、MySQL、H2 等
Jaeger链路追踪为主多协议多语言(OpenTelemetry)Cassandra、ES 等
Zipkin经典链路追踪B3 / W3C多语言ES、内存等
PinpointJava 全栈自动追踪自有协议以 Java 为主HBase

SkyWalking 的特色是把 Trace、Metric、Topology、告警整合到一个平台,且对 Java 生态的字节码插桩很成熟。

生态与标准演进

阶段/标准说明
Dapper(2010)论文提出 Trace/Span 模型
OpenTracing(2016)定义 Trace/Span 与 Inject/Extract API 规范
OpenCensus(2018)Google 的采集库
OpenTelemetry(2019 起)OpenTracing + OpenCensus 合并,成为云原生观测统一标准,主导规范
W3C Trace Context跨厂商的 HTTP 传播协议标准

新一代项目会优先兼容 OpenTelemetry。SkyWalking 既保留自有协议,也支持通过 OpenTelemetry Receiver 接入 OTel 数据。

小结

APM 的核心不是"多一个监控页面",而是用标准化的 Trace / Span 模型 + 跨进程上下文传播,把微服务下散落的请求还原成完整链路,进而支撑指标聚合、拓扑生成和故障定位。理解 Dapper 模型与上下文传播,是读懂任何 APM 平台(包括 SkyWalking)的前提。

基于现有 2.base.md核心功能 / 关键概念 / 端口已拆分到后面的架构篇;本页重点讲基础概念。