什么是链路追踪?分布式系统如何实现链路追踪?( 二 )


理解了这三个概念,接下来我们就看看分布式追踪系统是如何采集图中的微服务调用链 。

什么是链路追踪?分布式系统如何实现链路追踪?

文章插图
我们可以看到底层有一个 Collector 一直在默默无闻地收集数据,那么每一次调用 Collector 会收集哪些信息呢 。
  1. 全局 trace_id:这是显然的,这样才能把每一个子调用与最初的请求关联起来
  2. span_id: 图中的 0,1,1.1,2,这样就能标识是哪一个调用
  3. parent_span_id:比如 b 调用 d 的 span_id 是 1.1,那么它的 parent_span_id 即为 a 调用 b 的 span_id 即 1,这样才能把两个紧邻的调用关联起来 。
有了这些信息,Collector 收集的每次调用的信息如下:
什么是链路追踪?分布式系统如何实现链路追踪?

文章插图
根据这些图表信息显然可以据此来画出调用链的可视化视图如下:
什么是链路追踪?分布式系统如何实现链路追踪?

文章插图
于是一个完整的分布式追踪系统就实现了 。
以上实现看起来确实简单,但有以下几个问题需要我们仔细思考一下:
  1. 怎么自动采集 span 数据:自动采集,对业务代码无侵入
  2. 如何跨进程传递 context
  3. traceId 如何保证全局唯一
  4. 请求量这么多采集会不会影响性能
接下来,我们来看看链路追踪系统 SkyWalking 是如何解决以上四个问题的 。
链路追踪系统SkyWalking的原理1、怎么自动采集 span 数据
SkyWalking 采用了插件化 + javaagent 的形式来实现了 span 数据的自动采集,这样可以做到对代码的无侵入性 。插件化意味着可插拔,扩展性好 。如下图所示:
什么是链路追踪?分布式系统如何实现链路追踪?

文章插图
2、如何跨进程传递 context
我们知道数据一般分为 header 和 body,就像 http 有 header 和 body,RocketMQ 也有 MessageHeader,Message Body 。body 一般放着业务数据,所以不宜在 body 中传递 context,应该在 header 中传递 context,如图所示:
什么是链路追踪?分布式系统如何实现链路追踪?

文章插图
dubbo 中的 attachment 就相当于 header,所以我们把 context 放在 attachment 中,这样就解决了 context 的传递问题 。
什么是链路追踪?分布式系统如何实现链路追踪?

文章插图
3、traceId 如何保证全局唯一
要保证全局唯一 ,我们可以采用分布式或者本地生成的 ID 。使用分布式的话,需要有一个发号器,每次请求都要先请求一下发号器,会有一次网络调用的开销 。所以 SkyWalking 最终采用了本地生成 ID 的方式,它采用了大名鼎鼎的 snowflow 算法,性能很高 。
什么是链路追踪?分布式系统如何实现链路追踪?

文章插图
snowflake 算法生成的 id
不过 snowflake 算法有一个众所周知的问题:时间回拨,这个问题可能会导致生成的 id 重复 。那么 SkyWalking 是如何解决时间回拨问题的呢 。
什么是链路追踪?分布式系统如何实现链路追踪?

文章插图
每生成一个 id,都会记录一下生成 id 的时间(lastTimestamp),如果发现当前时间比上一次生成 id 的时间(lastTimestamp)还小,那说明发生了时间回拨,此时会生成一个随机数来作为 traceId 。这里可能就有同学要较真了,可能会觉得生成的这个随机数也会和已生成的全局 id 重复,是否再加一层校验会好点 。
这里要说一下系统设计上的方案取舍问题了,首先如果针对产生的这个随机数作唯一性校验无疑会多一层调用,会有一定的性能损耗,但其实时间回拨发生的概率很小(发生之后由于机器时间紊乱,业务会受到很大影响,所以机器时间的调整必然要慎之又慎),再加上生成的随机数重合的概率也很小,综合考虑这里确实没有必要再加一层全局唯一性校验 。对于技术方案的选型,一定要避免过度设计,过犹不及 。
4、请求量这么多,全部采集会不会影响性能?
如果对每个请求调用都采集,那毫无疑问数据量会非常大,但反过来想一下,是否真的有必要对每个请求都采集呢?其实没有必要,我们可以设置采样频率,只采样部分数据,SkyWalking 默认设置了 3 秒采样 3 次,其余请求不采样,如图所示:
什么是链路追踪?分布式系统如何实现链路追踪?

文章插图
这样的采样频率其实足够我们分析组件的性能了,按 3 秒采样 3 次,这样的频率来采样数据会有啥问题呢 。理想情况下,每个服务调用都在同一个时间点,这样的话每次都在同一时间点采样确实没问题 。如下图所示:


推荐阅读