3、Jaeger链路追踪基础:分布式追踪原理、Span与Trace概念、Jaeger架构与OpenTelemetry标准

3.1 分布式追踪原理:从单机到微服务的观测鸿沟

在单体应用时代,一次请求的完整调用链可以通过单一进程内的日志或堆栈轻松串联。进入微服务架构后,一个用户请求可能跨越数十个服务实例、消息队列、数据库和缓存,传统的日志聚合方式无法高效还原请求的完整路径。分布式追踪的核心思想是:为每个请求注入一个全局唯一的 Trace ID,并在每个服务节点记录带有时间戳和父子关系的 Span,最终通过后端系统将这些分散的数据拼接成完整的调用拓扑。

核心挑战: 分布式环境下的时钟不同步、网络延迟、异步调用、多线程并发,要求追踪系统具备高精度的时间校正能力和灵活的上下文传播机制。

3.2 Span 与 Trace:分布式追踪的原子单元与全局视图

分布式追踪的数据模型由两个核心概念构成:Span 和 Trace。

概念 定义 关键属性 类比
Span 一次操作或工作单元的描述,包含操作名称、开始时间、结束时间、状态和标签。 Span ID、Parent Span ID、Trace ID、Operation Name、Start Time、Duration、Tags、Logs 函数调用栈中的一帧
Trace 由一组具有相同 Trace ID 的 Span 构成的树状结构,完整描述一次请求从入口到出口的完整路径。 Trace ID、根 Span、Span 层级关系、服务拓扑 完整的函数调用栈

Span 的生命周期:

  1. 开始(Start):记录操作开始时间戳。
  2. 注入上下文(Inject):将 Span 上下文(Trace ID + Span ID)传播到下游服务(通过 HTTP Header、gRPC Metadata 等)。
  3. 添加标签与日志(Tag & Log):记录关键业务属性(如订单ID、错误码)和事件(如缓存命中、异常堆栈)。
  4. 结束(Finish):记录结束时间戳,计算耗时,并上报给 Collector。
最佳实践: 每个 Span 应代表一个有意义的业务或系统操作,避免粒度过细(如循环内每行代码一个 Span)或过粗(如整个 HTTP 请求一个 Span)。通常建议 Span 的粒度对应一次外部调用、一次数据库查询或一个核心业务步骤。
Trace 与 Span 树状结构关系 Root Span (Trace ID: A) Span B: 用户服务 Span C: 订单服务 Span D: 支付服务 Span E: MySQL 查询 Span F: Redis 缓存 Span G: 支付网关 说明: • 每个 Span 包含唯一的 Span ID 和 Parent Span ID,形成父子层级。 • 所有 Span 共享同一个 Trace ID,通过 Trace ID 聚合为完整的调用链。 • 根 Span 没有父 Span,通常代表入口请求(如 API 网关接收到的 HTTP 请求)。

3.3 Jaeger 架构:四大核心组件与数据流

Jaeger 是 CNCF 毕业的分布式追踪系统,其架构由四个核心组件构成:Agent、Collector、Query 和 UI。此外,后端存储通常依赖 Cassandra、Elasticsearch 或 Kafka。

组件 职责 部署模式 关键配置
Agent 作为 DaemonSet 或 Sidecar 部署在每个节点上,接收应用通过 UDP 发送的 Span 数据,批量转发给 Collector。 Sidecar / DaemonSet 端口 6831 (UDP)、端口 5778 (采样策略)
Collector 接收 Agent 或应用直接发送的 Span,进行校验、索引、存储,并支持通过 Kafka 实现缓冲和削峰。 Deployment / StatefulSet 端口 14250 (gRPC)、端口 14268 (HTTP)
Query 提供 API 接口,从存储中检索 Trace 数据,供 UI 展示。 Deployment 端口 16686 (HTTP API + UI)
UI 基于 React 构建的 Web 界面,提供 Trace 搜索、Span 详情查看、服务拓扑图、性能分析等功能。 与 Query 同进程 集成在 Query 端口 16686
生产环境注意事项: Agent 与应用程序同节点部署,避免网络抖动导致数据丢失。Collector 建议启用 Kafka 作为缓冲层,防止存储后端故障时丢失 Trace 数据。Query 服务应配置合理的缓存策略,避免高并发查询压垮存储层。
Jaeger 架构组件与数据流 微服务 A (OpenTelemetry SDK) 微服务 B (OpenTelemetry SDK) 微服务 C (OpenTelemetry SDK) Jaeger Agent Jaeger Agent Jaeger Agent Jaeger Collector (gRPC / HTTP / Kafka) 存储后端 (ES / Cassandra / Kafka) Jaeger Query + UI (端口 16686) 数据流方向: 应用 SDK → Agent (UDP) → Collector (gRPC/HTTP) → 存储后端 → Query → UI 可选路径:应用 SDK 可直接通过 HTTP/gRPC 发送 Span 给 Collector,绕过 Agent。

3.4 OpenTracing 与 OpenTelemetry:标准演进与 Jaeger 的适配

在 Jaeger 的发展历程中,先后经历了 OpenTracing 和 OpenTelemetry 两个标准阶段。理解这两个标准的关系,对于正确集成 Jaeger 至关重要。

标准 状态 核心 API Jaeger 支持方式
OpenTracing 已合并到 OpenTelemetry(停止独立演进) Tracer、Span、SpanContext、Inject/Extract Jaeger 原生支持 OpenTracing API(jaeger-client)
OpenTelemetry (OTel) CNCF 毕业项目,当前标准 TracerProvider、SpanProcessor、Exporter、Context Propagation Jaeger 支持 OTel 协议(OTLP),推荐使用 OTel SDK 采集数据
迁移建议: 新项目应直接使用 OpenTelemetry SDK 进行埋点,并通过 OTLP Exporter 将数据发送到 Jaeger Collector(需启用 OTLP 接收端)。已有 OpenTracing 埋点的项目,Jaeger 仍提供兼容性支持,但建议逐步迁移到 OpenTelemetry。

OpenTelemetry 与 Jaeger 的集成方式:

  1. 直接导出(OTLP):应用通过 OTel SDK 的 OTLP Exporter 将 Span 数据直接发送到 Jaeger Collector(端口 4317 gRPC / 4318 HTTP)。
  2. 通过 Jaeger Exporter:OTel SDK 提供 Jaeger Exporter,可将数据格式转换为 Jaeger 原生协议,发送到 Jaeger Agent 或 Collector。
  3. 通过 Collector 中转:使用 OpenTelemetry Collector 作为中间层,接收 OTLP 数据后,再转发给 Jaeger Collector 或其他后端。
推荐方案: 在 Kubernetes 环境中,使用 OpenTelemetry Operator 自动注入 Sidecar,配合 OpenTelemetry Collector 作为统一的遥测数据管道,最终将 Trace 数据发送到 Jaeger 后端。这种方式可以解耦应用与后端,便于统一管理采样策略和数据路由。