2. Tempo 架构概览:核心组件、数据流与角色职责

在深入存储调优之前,必须先理解 Tempo 的架构骨架。Tempo 采用微服务架构,核心组件各司其职,通过异步管道协同完成从数据接收到查询响应的全流程。本章将拆解每个组件的职责、数据流转路径以及它们在性能调优中的关键角色。

2.1 核心组件与角色职责

Tempo 由四个主要组件构成:Distributor、Ingester、Querier 和 Compactor。每个组件均可独立水平扩展,这也是 Tempo 能够支撑大规模分布式追踪场景的基础。

组件 核心职责 调优关注点
Distributor 接收 Trace 数据,进行校验、采样、负载均衡,并转发至 Ingester 接收速率、gRPC 连接池、哈希一致性
Ingester 将 Trace 数据写入后端存储(如 S3/GCS),并维护内存中的最近数据索引 内存上限、Flush 策略、写入吞吐
Querier 接收查询请求,从 Ingester 内存和存储后端检索 Trace 数据 查询并发、缓存命中、索引扫描效率
Compactor 合并存储后端的小文件,减少碎片,优化查询扫描范围 合并周期、并行度、存储 IO 开销
调优视角: 在值班台场景中,Ingester 的内存配置和 Compactor 的合并策略直接影响查询延迟。如果 Ingester 频繁 OOM 或 Compactor 合并不及时,查询性能会急剧下降。

2.2 数据流全景:从接收到查询

一条 Trace 数据从被采集到最终可被查询,经历四个阶段。理解这个流程是定位性能瓶颈的前提。

  1. 接收与分发: 应用通过 OpenTelemetry SDK 或 Jaeger Agent 将 Trace 发送至 Distributor。Distributor 根据 TraceID 进行一致性哈希,将数据路由到对应的 Ingester 实例。
  2. 写入与缓冲: Ingester 将接收到的 Span 数据暂存于内存中,并定期 Flush 到后端存储(如对象存储或 Cassandra)。内存中的数据同时用于近期查询。
  3. 合并与优化: Compactor 异步扫描存储后端,将多个小文件合并为更大的块,减少存储碎片并优化索引结构。
  4. 查询与检索: Querier 接收用户查询,先向所有 Ingester 发起请求获取内存中的最新数据,再扫描存储后端中的历史数据,最终合并结果返回。
Tempo 核心数据流架构图 Tempo 核心数据流架构图 应用 / SDK Distributor Ingester 存储后端 Compactor Querier 用户 / 查询 数据流说明 ① 应用 → Distributor ② Distributor → Ingester ③ Ingester → 存储后端 ④ Compactor 合并优化 ⑤ Querier 查询检索

2.3 组件间通信与关键交互

组件之间的通信方式直接影响延迟和可靠性。Tempo 主要使用 gRPC 进行内部通信,并依赖一致性哈希实现数据路由。

  • Distributor ↔ Ingester: 使用 gRPC 流式传输,Distributor 根据 TraceID 的哈希值将数据发送到对应的 Ingester 副本。此环节的瓶颈通常出现在 Distributor 的 gRPC 连接池大小和 Ingester 的接收队列深度。
  • Ingester ↔ 存储后端: Ingester 将数据以 Parquet 格式写入对象存储(推荐)或 Cassandra。写入频率由 ingester.flush-check-period 和 ingester.trace-idle-period 控制。
  • Querier ↔ Ingester: 查询时,Querier 并行向所有 Ingester 发起 gRPC 请求,获取内存中的最新数据。如果 Ingester 响应慢,会直接拖累查询 P99 延迟。
  • Compactor ↔ 存储后端: Compactor 定期扫描存储桶中的小文件,合并后重新写入。合并后的块越大,Querier 扫描时的索引效率越高。
性能调优提示: 在值班台场景中,如果发现查询延迟波动大,优先检查 Ingester 的内存使用率 和 Compactor 的合并进度。Ingester 内存过高会导致 GC 停顿,Compactor 落后会导致存储碎片化。

2.4 数据模型与存储结构

Tempo 将 Trace 数据组织为 Block 和 Index 两层结构。理解这一模型是调优存储性能的前提。

概念 说明 调优影响
Block 包含多个 Trace 的 Span 数据,以 Parquet 列式格式存储 Block 大小影响 Compactor 合并效率与 Querier 扫描范围
Index 记录 Block 中 TraceID 的偏移量,用于快速定位 索引粒度越细,查询越快,但索引文件越大
Tenant 多租户隔离,每个租户拥有独立的 Block 和 Index 空间 租户数量影响存储布局和查询路由
Block 与 Index 存储结构示意图 Block 与 Index 存储结构示意图 Tenant: production Block 1 TraceID: 0x1A2B.. Span 数: 1200 Block 2 TraceID: 0x3C4D.. Span 数: 850 Block 3 TraceID: 0x5E6F.. Span 数: 2100 Index: 记录每个 Block 中 TraceID 的偏移量,加速查询定位 每个 Block 独立存储

2.5 关键配置参数速查

以下参数是值班台调优中最常触及的配置项,直接影响组件行为。

组件 参数 默认值 调优建议
Distributor distributor.receiver.max-recv-msg-size 16 MB 大 Trace 场景可提升至 64 MB
Ingester ingester.max-block-duration 30m 降低至 10m 可减少内存压力,但增加存储碎片
Ingester ingester.trace-idle-period 10s 短 Trace 场景可降至 5s,加速 Flush
Compactor compactor.compaction-interval 30m 高写入场景缩短至 15m,减少碎片窗口
Querier querier.max-concurrent-queries 20 根据 CPU 核数调整,通常设为 2×CPU 核数
避坑提醒: 不要盲目调小 ingester.max-block-duration。虽然能降低内存占用,但会导致 Compactor 合并大量小文件,反而增加存储 IO 和查询延迟。建议结合写入速率和存储类型(SSD vs 对象存储)综合评估。

2.6 值班台实战视角:组件健康检查清单

在值班台日常巡检中,建议关注以下指标,快速定位组件级问题。

  • Distributor: 检查 tempo_distributor_bytes_received_total 是否平稳,如果出现陡降,可能是上游 SDK 或网络问题。
  • Ingester: 监控 tempo_ingester_live_traces 和 process_resident_memory_bytes。如果内存持续增长且不回落,说明 Flush 阻塞。
  • Compactor: 观察 tempo_compactor_blocks_combined_total 和 tempo_compactor_errors_total。错误数突增通常意味着存储后端限流或权限问题。
  • Querier: 关注 tempo_querier_query_duration_seconds 的 P99 值。如果超过 5 秒,优先排查 Ingester 响应时间和存储索引效率。
总结: Tempo 的架构设计决定了调优的杠杆点。Distributor 负责入口流量控制,Ingester 是内存与写入的平衡点,Compactor 影响存储布局,Querier 是查询性能的最终体现。掌握每个组件的角色和数据流,才能在值班台场景中快速定位瓶颈。