链路追踪:概念、原理与数据采集

作者: IT Sectr 发布日期: 2026-05-29 阅读时间: 8 分钟

链路追踪是一种通过分布式系统观察请求流的方法,每个处理步骤都作为独立事件记录时间戳。根据OpenTelemetry 2025年数据,一个trace将请求从入口点到最终响应的完整路径连接起来,经过所有微服务和外部调用。这使开发人员能够在复杂的移动后端架构中发现瓶颈、延迟和故障。

要点

  • 链路追踪 — 记录请求通过分布式系统所有组件的路径,并记录每一步的时间。
  • Span — 追踪的基本单元,代表一个操作,记录开始和结束时间。
  • 分布式追踪 — 通过上下文传递将不同服务的span连接成单一trace链的机制。
  • OpenTelemetry — 支持所有流行语言和平台的遥测数据收集标准。
  • 采样 — 选择部分请求进行追踪的策略,用于控制数据量和存储成本。

监控中的链路追踪是什么

链路追踪是一种分布式观察方法,每个传入请求都会通过系统的所有服务和组件进行跟踪。与显示聚合值(平均响应时间、错误数量)的指标不同,追踪保留了一个特定请求的完整上下文。

每个处理步骤——数据库调用、对另一个微服务的HTTP请求、后台任务的执行——都作为独立单元记录,包含时间戳、状态和属性。根据Google Dapper(2010年原始发布)的数据,追踪能够在分布式系统中定位延迟,精确到单个调用。

追踪对于移动应用尤其重要,因为其后端由数十个微服务组成。用户操作——例如登录账户——可能经过API网关、认证服务、数据库和推送服务。没有trace,几乎无法确定哪个组件拖慢了响应速度。

Span和Trace:基本数据结构

追踪的基本单元是span。每个span代表一个逻辑操作:HTTP请求、SQL查询、gRPC调用、JSON序列化。Span包含唯一标识符、父标识符、操作名称、开始时间、持续时间、状态和一组属性。

Trace中的Span层次结构

所有属于同一个根请求的span合并成一个trace。根span代表入口点——从移动客户端到API的HTTP请求。子span形成一棵树,每个span通过parent_span_id字段引用其父级。

trace的持续时间等于所有span唯一时间段的总和。如果两个子span并行执行,它们的时间不会相加——这对于正确分析由微服务并行调用引起的延迟至关重要。

Span的属性和事件

每个span可以包含属性——带有元信息的键值对:请求URL、用户ID、API版本、主机名。属性用于过滤和分组trace。除属性外,span还支持事件——带有文本描述的时间戳,例如“缓存未命中”或“重新连接尝试”。

分布式追踪的工作原理

分布式追踪解决了在不同进程和不同机器上创建的span的连接问题。该机制基于上下文传递:当从服务A调用服务B时,会在出站请求中添加一个包含当前trace和父span标识符的标头。

上下文传递的标准协议——W3C Trace Context(traceparent和tracestate标头)和Zipkin B3(X-B3-TraceId、X-B3-SpanId标头)。W3C Trace Context于2021年被W3C联盟采纳为标准,并得到所有主要遥测供应商的支持。

接收请求时,服务B从标头中提取trace_id,并使用该trace_id创建一个子span。这样,请求完成后,来自不同服务的所有span在收集器端合并成一个trace。为此,每个服务必须使用相同的追踪库进行仪表化。

微服务中的上下文传递

在移动开发中,上下文传递不仅涵盖后端,还包括客户端-服务器交互。移动应用可以在每个API请求的标头中发送trace_id,从而将客户端操作与服务器处理关联起来。适用于iOS和Android的OpenTelemetry SDK支持通过HTTP客户端自动创建和传递trace上下文。

kotlin
import io.opentelemetry.api.trace.Span
import io.opentelemetry.api.trace.Tracer
import io.opentelemetry.context.Context

class TracingInterceptor : Interceptor {
    private val tracer: Tracer = OpenTelemetry.getTracer("mobile-app")

    override fun intercept(chain: Interceptor.Chain): Response {
        val span = tracer.spanBuilder("HTTP POST /api/login")
            .setParent(Context.current())
            .startSpan()

        return chain.proceed(chain.request())
            .also { span.end() }
    }
}

Kotlin中展示的拦截器为每个对服务器的HTTP请求创建一个span。父上下文通过Context.current()从调用代码传递,这使得客户端侧trace可以与服务器侧trace关联。

通过OpenTelemetry实现追踪

OpenTelemetry是收集trace数据的事实标准。它提供了统一的API来生成span,自动检测流行库,以及灵活的机制将数据导出到不同的后端:Jaeger、Zipkin、Grafana Tempo、Datadog、New Relic。

自动检测

OpenTelemetry支持自动为流行框架创建span:Spring Boot、Ktor、Flask、Express、gRPC。开发人员只需向项目添加依赖,库就会自动拦截传入和传出的请求。Java的自动检测使用javaagent,它在不修改源代码的情况下动态修改字节码。

针对移动平台,OpenTelemetry提供了Swift SDK和Kotlin SDK。它们自动为网络请求(URLSession、OkHttp)、数据库操作(CoreData、Room)和后台任务创建span。开发人员可以为业务逻辑添加自定义span。

数据导出

收集到的span通过OTLP(OpenTelemetry协议)发送到收集器。收集器可以缓冲、过滤和将数据导向一个或多个存储系统。根据OpenTelemetry文档,使用gRPC导出时,从生成span到其在仪表板上显示的典型延迟为2至5秒。

swift
import OpenTelemetryApi
import OpenTelemetrySdk
import URLSessionInstrumentation

let instrumentation = URLSessionInstrumentation()
instrumentation.enable()

let tracer = OpenTelemetry.instance.tracerFactory
    .get("mobile-monitoring")

let span = tracer.spanBuilder("fetch-user-profile")
    .setAttribute(key: "user.id", value: userId)
    .startSpan()
span.end()

Swift中的代码激活网络层的自动检测,并为获取用户配置文件的操作创建自定义span。user.id属性允许随后按特定用户过滤trace。

Trace采样策略

在高负载系统中,不可能追踪每个请求——这会给存储和网络带来不可接受的负载。采样通过仅保存部分trace来解决此问题。策略的选择直接影响到数据的完整性和基础设施成本。

基于头部的采样

关于是否保存trace的决定在其创建时刻做出——在根span中。最简单且最常用的方法:固定百分比的请求(例如5%)被保存,其余的丢弃。缺点——不能保证罕见的错误会被捕获。OpenTelemetry中的概率采样器支持设置0.0到1.0之间的概率。

基于尾部的采样

决定推迟到trace的所有span完成之后。分析器评估trace是否包含错误、超时或有趣的属性,然后才保存它。这种方法需要在收集器中缓冲所有span,这增加了内存消耗。根据Grafana Labs的数据,在罕见但关键错误的系统中,尾部采样在“有用数据价格”比率方面效率高出40-60%。

策略优点缺点
Fixed probability简单,可预测的负载遗漏罕见事件
Rate limiting数据量有保障覆盖不均匀
Tail-based捕获所有错误高内存消耗
Adaptive成本与覆盖的平衡配置复杂

追踪与日志记录的区别

日志记录记录独立事件及其重要性级别(info、warn、error),但不会将它们关联到单个请求的上下文中。相反,追踪创建了一个属于端到端请求的结构化操作树。在实践中,这两种方法并不相互排斥,而是相互补充。

日志对于特定错误的详细分析非常有效:开发人员可以看到确切的消息、堆栈跟踪和变量值。追踪回答了“为什么请求需要5秒”的问题——它显示哪个微服务或调用占用了最多的时间。根据Honeycomb(2024年)的数据,将追踪与日志记录结合使用的团队发现事件根本原因的速度提高了2.3倍。

现代方法——可观测性——将trace、指标和日志整合到一个统一系统中。OpenTelemetry支持这三个信号之间的关联:每个span可以包含指向相关日志的引用,指标可以用trace_id标记以导航到特定的trace。

常见问题

追踪与监控有什么区别?

监控显示系统的聚合指标——平均响应时间、每分钟错误数、CPU负载。追踪显示一个特定请求经过所有组件的路径。监控回答“发生了什么”,追踪回答“为什么发生”。

需要追踪百分之多少的请求?

对于生产系统,头部采样时1-5%的请求就足够了。如果系统很少产生错误,建议使用尾部采样,专注于捕获所有错误的trace。对于staging环境,允许无限制地追踪100%的请求。

哪些工具支持分布式追踪?

主要工具:Jaeger(Uber的解决方案,开源)、Grafana Tempo(可扩展的trace存储)、Datadog APMNew Relic Distributed TracingAWS X-RayHoneycomb。它们都支持OpenTelemetry标准进行数据接收。

能否在没有后端的情况下追踪移动应用?

可以,本地追踪在单个进程内工作。适用于iOS和Android的OpenTelemetry SDK为本地操作创建span:从数据库读取、图像处理、网络请求。这类trace不是分布式的,但对于诊断客户端性能非常有用。

追踪如何影响应用程序性能?

现代追踪库在头部采样时增加不到1%的开销。OpenTelemetry使用异步数据导出,不会阻塞主线程。对于移动设备,建议限制创建span的频率并使用自适应采样策略。

总结

  • 链路追踪是一种观察方法,记录每个请求通过分布式系统所有组件的路径,精确到单个操作。
  • Span是trace的基本单元,包含操作名称、持续时间、状态和属性。
  • 分布式追踪是通过trace_id上下文传递连接来自不同服务的span的机制。
  • OpenTelemetry是收集trace数据的标准,支持自动检测和多个后端。
  • 采样可以控制保存的trace量——头部采样简单,尾部采样捕获罕见错误。
  • 追踪与日志和指标结合,提供系统可观测性的完整图景。
  • 建议从关键场景开始实施分布式追踪——认证、支付、数据加载——然后逐步扩展到所有服务。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读