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 的生命周期:
- 开始(Start):记录操作开始时间戳。
- 注入上下文(Inject):将 Span 上下文(Trace ID + Span ID)传播到下游服务(通过 HTTP Header、gRPC Metadata 等)。
- 添加标签与日志(Tag & Log):记录关键业务属性(如订单ID、错误码)和事件(如缓存命中、异常堆栈)。
- 结束(Finish):记录结束时间戳,计算耗时,并上报给 Collector。
最佳实践: 每个 Span 应代表一个有意义的业务或系统操作,避免粒度过细(如循环内每行代码一个 Span)或过粗(如整个 HTTP 请求一个 Span)。通常建议 Span 的粒度对应一次外部调用、一次数据库查询或一个核心业务步骤。
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 服务应配置合理的缓存策略,避免高并发查询压垮存储层。
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 的集成方式:
- 直接导出(OTLP):应用通过 OTel SDK 的 OTLP Exporter 将 Span 数据直接发送到 Jaeger Collector(端口 4317 gRPC / 4318 HTTP)。
- 通过 Jaeger Exporter:OTel SDK 提供 Jaeger Exporter,可将数据格式转换为 Jaeger 原生协议,发送到 Jaeger Agent 或 Collector。
- 通过 Collector 中转:使用 OpenTelemetry Collector 作为中间层,接收 OTLP 数据后,再转发给 Jaeger Collector 或其他后端。
推荐方案: 在 Kubernetes 环境中,使用 OpenTelemetry Operator 自动注入 Sidecar,配合 OpenTelemetry Collector 作为统一的遥测数据管道,最终将 Trace 数据发送到 Jaeger 后端。这种方式可以解耦应用与后端,便于统一管理采样策略和数据路由。