分布式链路追踪 SkyWalking 源码分析 —— Agent 收集 Trace 数据

点击上方“芋道源码”,选择“设为星标

做积极的人,而不是积极废人!

源码精品专栏

 

本文主要基于 SkyWalking 3.2.6 正式版

  • 1. 概述

  • 2. Trace

    • 2.1 ID

    • 2.2 AbstractSpan

    • 2.3 TraceSegmentRef

  • 2.4 TraceSegment

  • 3. Context

    • 3.1 ContextManager

    • 3.2 AbstractTracerContext

    • 3.3 SamplingService


1. 概述

分布式链路追踪系统,链路的追踪大体流程如下:

  1. Agent 收集 Trace 数据

  2. Agent 发送 Trace 数据给 Collector 。

  3. Collector 接收 Trace 数据。

  4. Collector 存储 Trace 数据到存储器,例如,数据库。

本文主要分享【第一部分】 SkyWalking Agent 收集 Trace 数据。文章的内容顺序如下:

  • Trace 的数据结构

  • Context 收集 Trace 的方法

不包括插件对 Context 收集的方法的调用,后续单独文章专门分享,胖友也可以阅读完本文后,自己去看 apm-sdk-plugin 的实现代码。

本文涉及到的代码如下图:

640?wx_fmt=jpeg
  • 红框部分:Trace 的数据结构,在 「2. Trace」 分享。

  • 黄框部分:Context 收集 Trace 的方法,在 「3. Context」 分享。

2. Trace

友情提示:胖友,请先行阅读 《OpenTracing语义标准》 。

本小节,笔者认为胖友已经对 OpenTracing 有一定的理解。

org.skywalking.apm.agent.core.context.trace.TraceSegment ,是一次分布式链路追踪( Distributed Trace ) 的一段

  • 一条 TraceSegment ,用于记录所在线程( Thread )的链路。

  • 一次分布式链路追踪,可以包含多条 TraceSegment ,因为存在跨进程( 例如,RPC 、MQ 等等),或者垮线程( 例如,并发执行、异步回调等等 )。

TraceSegment 属性,如下:

  • traceSegmentId 属性,TraceSegment 的编号,全局唯一。在 「2.1 ID」 详细解析。

  • refs 属性,TraceSegmentRef 数组,指向的 TraceSegment 数组。

    • 为什么会有多个爸爸?下面统一讲。

    • TraceSegmentRef ,在 「2.3 TraceSegmentRef」 详细解析。

  • relatedGlobalTraces 属性,关联的 DistributedTraceId 数组

    • 为什么会有多个爸爸?下面统一讲。

    • DistributedTraceId ,在 「2.1.2 DistributedTraceId」 详细解析。

  • spans 属性,包含的 Span 数组。在 「2.2 AbstractSpan」 详细解析。这是 TraceSegment 的主体,总的来说,TraceSegment 是 Span 数组的封装。

  • ignore 属性,是否忽略该条 TraceSegment 。在一些情况下,我们会忽略 TraceSegment ,即不收集链路追踪,在下面 「3. Context」 部分内容,我们将会看到这些情况。

  • isSizeLimited 属性,Span 是否超过上限( `Config.Agent.SPAN_LIMIT_PER_SEGMENT` )。超过上限,不在记录 Span 。

为什么会有多个爸爸

  • 我们先来看看一个爸爸的情况,常见于 RPC 调用。例如,【服务 A】调用【服务 B】时,【服务 B】新建一个 TraceSegment 对象:

    • 将自己的 `refs` 指向【服务 A】的 TraceSegment 。

    • 将自己的 `relatedGlobalTraces` 设置为 【服务 A】的 DistributedTraceId 对象。

  • 我们再来看看多个爸爸的情况,常见于 MQ / Batch 调用。例如,MQ 批量消费消息时,消息来自【多个服务】。每次批量消费时,【消费者】新建一个 TraceSegment 对象:

    • 将自己的 `refs` 指向【多个服务】的多个 TraceSegment 。

    • 将自己的 `relatedGlobalTraces` 设置为【多个服务】的多个 DistributedTraceId 。

友情提示:多个爸爸的故事,可能比较难懂,等胖友读完全文,在回过头想想。或者拿起来代码调试调试。

下面,我们来具体看看 TraceSegment 的每个元素,最后,我们会回过头,在 「2.4 TraceSegment」 详细解析它。

2.1 ID

org.skywalking.apm.agent.core.context.ids.ID ,编号。从类的定义上,这是一个通用的编号,由三段整数组成。

目前使用 GlobalIdGenerator 生成,作为全局唯一编号。属性如下:

  • part1 属性,应用实例编号。

  • part2 属性,线程编号。

  • part3 属性,时间戳串,生成方式为 ${时间戳} * 10000 + 线程自增序列([0, 9999]) 。例如:15127007074950012 。具体生成方法的代码,在 GlobalIdGenerator 中详细解析。

  • encoding 属性,编码后的字符串。格式为 "${part1}.${part2}.${part3}" 。例如,"12.35.15127007074950000" 。

    • 使用 `#encode()` 方法,编码编号。

  • isValid 属性,编号是否合法。

    • 使用 `ID(encodingString)` 构造方法,解析字符串,生成 ID 。

2.1.1 GlobalIdGenerator

org.skywalking.apm.agent.core.context.ids.GlobalIdGenerator ,全局编号生成器。

#generate() 方法,生成 ID 对象。代码如下:

  • 第 67 行:获得线程对应的 IDContext 对象。

  • 第 69 至 73 行:生成 ID 对象

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值