3. Tempo分布式追踪概述:Tempo架构、Span与Trace模型、Tempo与OpenTelemetry的关系

3.1 为什么SRE需要理解Tempo

在SLO违约根因定位场景中,MTTR(平均修复时间)的复盘口径高度依赖分布式追踪数据的完整性与查询效率。Grafana Tempo作为专为高基数、低成本设计的分布式追踪后端,与OpenTelemetry标准深度绑定,是构建可观测性平台的核心组件。理解Tempo的架构设计、Span与Trace的数据模型,以及它与OpenTelemetry的协作关系,是优化查询性能、缩短MTTR复盘口径的前提。

核心认知: Tempo不存储应用日志或指标,只存储追踪数据(Trace)。它通过对象存储(如S3、GCS)实现低成本持久化,并通过与OpenTelemetry Collector的集成实现无厂商锁定的数据采集。

3.2 Tempo架构全景

Tempo采用微服务架构,核心组件包括Distributor、Ingester、Querier、Compactor和Query Frontend。各组件职责清晰,通过gRPC/HTTP通信,支持水平扩展。

组件 职责 关键特性
Distributor 接收来自OpenTelemetry Collector或其他客户端的Span数据,进行验证、采样和负载均衡 无状态,支持Hash环分片,将Span转发至对应的Ingester
Ingester 将Span数据缓冲在内存中,并定期刷新到后端存储(对象存储) 有状态,支持WAL(Write-Ahead Log)防止数据丢失,默认每30秒刷新一次
Querier 接收查询请求,从Ingester(热数据)和后端存储(冷数据)中检索Trace 无状态,支持Trace ID精确查询和Service/Operation/Attributes组合查询
Compactor 合并后端存储中的小文件,减少存储碎片,提高查询效率 后台运行,可配置合并策略和保留周期
Query Frontend 作为查询层的入口,负责查询拆分、缓存和结果合并 支持查询分片、并行查询和结果缓存,显著降低查询延迟
MTTR复盘优化点: 在SLO违约场景中,Query Frontend的缓存机制可以加速对高频Trace ID的重复查询,建议将缓存TTL设置为与SLO评估窗口一致(如5分钟),避免冷查询拖慢复盘速度。
Tempo 核心架构与数据流 OpenTelemetry Collector Jaeger / Zipkin Agent Distributor 验证 / 采样 / 分片 Ingester 内存缓冲 + WAL 对象存储 S3 / GCS / Azure Blob Compactor Querier 热/冷数据检索 Query Frontend Grafana / API 用户 数据流方向 Collector → Distributor → Ingester → 对象存储 查询:用户 → Frontend → Querier

3.3 Span与Trace模型

Tempo的数据模型严格遵循OpenTelemetry规范。一个Trace由多个Span组成,每个Span代表分布式系统中的一次操作单元。Span之间通过SpanContext中的Trace ID和Span ID建立父子关系。

3.3.1 Span核心字段

字段 类型 说明 MTTR复盘用途
TraceId 16字节 全局唯一标识一次完整请求 关联所有相关Span,定位全链路
SpanId 8字节 标识单个Span 区分不同操作单元
ParentSpanId 8字节 父Span的ID,根Span为空 构建调用链拓扑
SpanKind 枚举 CLIENT / SERVER / INTERNAL / PRODUCER / CONSUMER 判断调用方向,识别上下游依赖
StartTime / EndTime 时间戳 Span的开始和结束时间 计算延迟,定位慢操作
Attributes 键值对 自定义元数据,如HTTP方法、状态码、DB语句 过滤和聚合,按服务/接口/错误码分组
Status OK / ERROR / UNSET 操作结果状态 快速识别失败Span,关联错误堆栈
Events 列表 带时间戳的日志事件,如异常抛出、缓存命中 补充诊断上下文

3.3.2 Trace树形结构

一个Trace在逻辑上构成一棵有向无环树(DAG),根Span代表入口请求(如HTTP API调用),子Span代表内部服务调用、数据库查询或消息发送。Tempo通过Trace ID聚合所有Span,并在查询时重建完整的调用链拓扑。

Trace 树形结构示例(一次下单请求) Root Span: POST /order Auth Service: 验证 Inventory Service: 检查库存 Payment Service: 扣款 MySQL: 更新库存表 Redis: 扣减缓存 每个矩形代表一个Span,箭头代表父子关系(ParentSpanId指向父Span)

3.4 Tempo与OpenTelemetry的关系

Tempo与OpenTelemetry(OTel)的关系可以概括为:OTel定义标准,Tempo实现存储与查询。具体体现在以下三个层面:

  • 数据协议层: Tempo原生支持通过OTLP(OpenTelemetry Protocol)接收Span数据,无需额外的协议转换器。OTel SDK和Collector可以直接将数据推送到Tempo的Distributor。
  • 数据模型层: Tempo内部存储的Span结构完全对齐OTel的Span模型,包括TraceId、SpanId、Attributes、Events等字段。这意味着在OTel中定义的任何属性都可以在Tempo中直接用于查询和过滤。
  • 生态集成层: Tempo与OpenTelemetry Collector深度集成,支持Collector的批量处理、采样、属性修改等预处理能力。同时,Tempo的查询语言TraceQL也兼容OTel的语义约定(Semantic Conventions),例如使用 http.status_code 或 db.system 作为查询条件。
常见误区: Tempo不是OpenTelemetry的替代品,而是其存储后端的一种实现。OTel负责数据的生成、采集和导出,Tempo负责数据的持久化、索引和检索。两者配合使用才能构建完整的分布式追踪体系。

3.4.1 数据采集链路对比

环节 OpenTelemetry Tempo
数据生成 OTel SDK(Java/Go/Python等) 不参与
数据采集 OTel Collector(Agent/Gateway模式) 不参与
数据传输 OTLP gRPC/HTTP 接收OTLP请求
数据存储 不参与 内存 + 对象存储
数据查询 不参与 TraceQL / 服务图
数据可视化 不参与 Grafana Explore / 服务图面板

3.5 本章小结

  • Tempo采用Distributor、Ingester、Querier、Compactor、Query Frontend五组件架构,支持水平扩展和低成本对象存储。
  • Span是追踪的最小单元,包含TraceId、SpanId、ParentSpanId、Attributes等关键字段;Trace由多个Span构成树形结构。
  • Tempo与OpenTelemetry是互补关系:OTel负责数据生成与采集,Tempo负责存储与查询,两者通过OTLP协议无缝对接。
  • 理解Tempo的架构和数据模型,是后续优化TraceQL查询、缩短MTTR复盘口径的基础。