Tracing

OpenTracing 数据模型

  • 1 分布式追踪的概念

  • 2 整体概念

    • 2.1 链路

  • 3 业界

  • 4 例子

    • 4.1 opentracing

      • 4.1.1 Scope & ScopeManager

      • 4.1.2 使用

1 分布式追踪的概念

谷歌在 2010 年 4 月发表了一篇论文《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》(http://1t.click/6EB),介绍了分布式追踪的概念。

对于分布式追踪,主要有以下的几个概念:

  • 追踪 Trace:就是由分布的微服务协作所支撑的一个事务。一个追踪,包含为该事务提供服务的各个服务请求。

  • 跨度 Span:Span 是事务中的一个工作流,一个 Span 包含了时间戳,日志和标签信息。Span 之间包含父子关系,或者主从(Followup)关系。

  • 跨度上下文 Span Context:跨度上下文是支撑分布式追踪的关键,它可以在调用的服务之间传递,上下文的内容包括诸如:从一个服务传递到另一个服务的时间,追踪的 ID,Span 的 ID 还有其它需要从上游服务传递到下游服务的信息。

2 整体概念

OpenTracing 中的调用链(Trace)通过归属于此调用链的 Span 来隐性地定义。一条调用链可以视为一个由多个 Span 组成的有向无环图(DAG 图)。Span 之间的关系被命名为 References。例如下面的示例调用链就是由 8 个 Span 组成的。

单个 Trace 中 Span 间的因果关系

有些情况下,使用下面这种基于时间轴的时序图可以更好地展现调用链。

单个 Trace 中 Span 间的时间关系

2.1 链路

Tracer 接口用于创建 Span(startSpan 函数)、解析上下文(Extract 函数)和透传上下文(Inject 函数)。它具有以下能力:

创建一个新 Span 或者设置 Span 属性

每个 Span 包含以下对象:

  • Operation name:操作名称 (也可以称作 Span name)。

  • Start timestamp:起始时间。

  • Finish timestamp:结束时间。

  • Span tag:一组键值对构成的 Span 标签集合。键值对中,键必须为 String,值可以是字符串、布尔或者数字类型。

  • Span log:一组 Span 的日志集合。每次 Log 操作包含一个键值对和一个时间戳。键值对中,键必须为 String,值可以是任意类型。

  • SpanContext: Span 上下文对象。每个 SpanContext 包含以下状态:

要实现任何一个 OpenTracing,都需要依赖一个独特的 Span 去跨进程边界传输当前调用链的状态(例如:Trace 和 Span 的 ID)。

Baggage Items 是 Trace 的随行数据,是一个键值对集合,存在于 Trace 中,也需要跨进程边界传输。

References(Span 间关系):相关的零个或者多个 Span(Span 间通过 SpanContext 建立这种关系)。

3 业界

  • Dapper(Google) : 各 tracer 的基础

  • StackDriver Trace (Google)

  • Zipkin(twitter)

  • Appdash(golang)

  • 鹰眼(taobao)

  • 谛听(盘古,阿里云云产品使用的Trace系统)

  • 云图(蚂蚁Trace系统)

  • sTrace(神马)

  • X-ray(aws)

4 例子

4.1 opentracing

  • SDK: https://github.com/opentracing/opentracing-python

  • eg: https://github.com/uber-common/opentracing-python-instrumentation

  • https://github.com/opentracing-contrib/python-flask

  • https://github.com/opentracing-contrib/python-django

4.1.1 Scope & ScopeManager

  • Scope 对象是 Active Span 的容器;

    • 通过 Scope 能拿到当前上下文内的 Active Span; _ThreadLocalScope 是 Scope 的一个实现,通过 ThreadLocal 来存储

  • ScopeManager 用来管理 Scope, ScopeManager 抽象了激活当前 Span 实例方法(via activate(Span)) 和 访问当前活跃 Span 实例的方法 (via activeSpan() );

    • ThreadLocalScopeManager 是 ScopeManager 的一个实现

Q: 为什么要抽象出 Scope 的概念?直接使用 ThreadLocal 存储 Span 不就可以了吗?

4.1.2 使用

Accessing the Active Span

Last updated