HelloWorld 分布式追踪指南

分布式追踪把一次跨多个服务的请求,变成一条可以阅读的时间线。HelloWorld指南会从“什么是span和trace”讲起,展示如何在服务里创建span、传播上下文、把数据导出到收集器并在后端可视化,同时讨论采样、性能影响与常见陷阱,给出可落地的配置与调优建议,并带示例。

HelloWorld 分布式追踪指南

先把概念讲清楚:分布式追踪的核心是什么

想像你点了一个外卖,订单通过下单服务、支付服务、库存服务、配送服务几次传递。分布式追踪就是在每个环节贴上一个时间标签和说明,把这些片段拼成一条完整的故事线,方便你看到哪一段慢、哪一步出错。

几个必须懂的名词

  • Trace:一次完整请求的全路径,由若干span组成。
  • Span:Trace中的一个单元,通常对应一次函数调用、一次HTTP请求或一次数据库操作,包含开始时间、结束时间、属性和事件。
  • Parent/Child:span之间的父子关系,用来组织调用链。
  • Context Propagation:把trace id和span id从一个服务传到另一个服务的方式(常见格式:W3C Trace Context)。
  • Sampling:决定保留多少追踪数据以节省成本的策略。

HelloWorld:从零到能看见第一条trace

下面按步骤来做,越简单越实用,目标是在本地运行两个服务(A 调用 B),看到一个从 A 到 B 的 trace。

准备工作(环境)

  • 选择语言和 SDK:推荐使用 OpenTelemetry(跨语言且活跃)。
  • 准备一个后端:本地可以用 Jaeger 或 Zipkin,也可以用 OpenTelemetry Collector 配合后端。
  • 确保服务可以互相通信(HTTP/gRPC),并能把 trace header 传递下去。

实施步骤(概念化,方便记忆)

  • 1. 初始化 Tracer:在服务启动时创建 TracerProvider 和导出器(exporter)。
  • 2. 在关键路径建 span:比如入口 HTTP handler 创建根 span,调用下游前创建子 span。
  • 3. 传播上下文:把 traceparent 或其他 header 带到下游请求头里。
  • 4. 导出:把采样后的 span 发送到 Collector 或后端。
  • 5. 在后端查看:用 Jaeger 的 UI 或 Zipkin 查看 trace。确认 parent-child 关系和时间线。

小贴士:如何在代码里想清楚 span 添写什么

  • span 名称用“动词+资源”形式,如 HTTP GET /orders
  • 把必要的属性(attributes)写清楚:方法、URL、状态码、db.statement(脱敏后)等。
  • 把异常用事件记录在 span 里,而不是只记录日志。

关键点详解(你会常犯的错误和如何避免)

上下文没有正确传播

最常见的问题:请求从 A 到 B,trace 信息丢失。排查方法:在发出 HTTP 请求时打印/检查是否携带 trace header。确保所有中间库(HTTP 客户端、消息中间件)都支持或允许传递 header。

采样策略不合理

简单的“全量”会把系统拖垮,过高的采样率会产生成本问题,过低会丢失关键问题。常用方案:

  • 固定采样(如 1%)用于长期监控。
  • 动态采样(基于错误或高延迟放大采样)。
  • 基于规则的采样(例如对关键用户或交易进行保留)。

性能影响被高估或低估

分布式追踪的成本主要来自网络发送、序列化与存储。实践中:

  • 使用批量导出减少网络请求次数。
  • 非阻塞发送(异步)防止阻塞主请求路径。
  • 尽量避免在高频短耗操作里创建大量细粒度 span(评估必要性)。

OpenTelemetry 常用落地配置(要点速览)

下面是一个简化思路,具体参数随 SDK 语言和版本不同而略有差异。

  • 启用资源(service.name、service.version)。
  • 配置采样器(ParentBased + TraceIdRatioBased 常见)。
  • 设置批量导出器(exporter)与上报间隔。
  • 启用自动注入 HTTP/gRPC/DB instrumentation(减少手工工作)。

示例:span 字段表

字段 作用
trace_id 标识一次完整请求
span_id 标识一个 span
parent_id 父 span 的 id(若有)
name 可读名字,如 HTTP GET /api
start/end 时间 用于计算耗时和可视化时间线
attributes / events 存放 key-value 信息和关键事件

如何把追踪和日志、指标结合起来

追踪告诉你“哪里慢了”,日志和指标补充“为什么慢”。实践建议:

  • 在 trace 上写入 trace_id 到日志(或使用自动注入),实现可跳转。
  • 在指标里打标签(tag)以便按服务/endpoint 聚合延迟分布。
  • 把错误率高的 trace 做为采样放大对象,便于事后分析。

进阶话题:消息队列、异步任务与 Baggage

异步系统里上下文传播更复杂,常见策略:

  • 把 trace header 放到消息属性(例如 Kafka message headers),消费方读取并继续创建子 span。
  • 慎用 baggage(会随每次请求传输,可能增大网络负担),只放小量关键元数据。
  • 对延迟敏感的任务,使用同步 span 或在任务入队时创建标记事件以便追溯。

常见排查流程(像在调真实服务那样)

  • 先看整体:是全链路都慢还是某个服务慢?
  • 定位单个 trace:看耗时最多的 span 和发生错误的 span。
  • 检查上下文是否断开(parent missing)以确认传播是否失败。
  • 对高延迟或高错误的路由,开启更高采样或抓取原始日志以复盘。

常见工具 / 名词参考(便于查文档)

  • OpenTelemetry(OTel)— SDK 与标准。
  • Jaeger / Zipkin — 常见的可视化后端。
  • OpenTelemetry Collector — 用于聚合、处理、导出 trace 的中间层。

写到这里我还想补一点:开始不要一上来就追求“完美”和“全覆盖”。先在关键业务路径上做起,保证 trace 的连续性和基本属性的规范,逐步扩展自动化与采样策略。实践中你会发现,分布式追踪更像做侦探工作,数据给出线索,工具帮你把线索串起来。祝你很快看到第一条从入口到数据库的完整时间线,那种“找到问题根源”的感觉,真是挺爽的。

返回首页