蚂蚁金服分布式链路跟踪组件 SOFATracer 总览 | 剖析

SOFAScalable  Open  Financial  Architecture)是蚂蚁金服自主研发的金融级分布式中间件,包含了构建金融级云原生架构所需的各个组件,是在金融场景里锤炼出来的最佳实践。

SOFATracer 是一个用于分布式系统调用跟踪的组件,通过统一的 TraceId 将调用链路中的各种网络调用情况以日志的方式记录下来,以达到透视化网络调用的目的,这些链路数据可用于故障的快速发现,服务治理等。

SOFATracerhttps://github.com/alipay/sofa-tracer

本文为《剖析 | SOFATracer 框架》第一篇。《剖析 | SOFASOFATracer 框架》系列由 SOFA 团队和源码爱好者们出品,项目代号:文章尾部有参与方式,欢迎同样对源码热情的你加入

0、前言

在单体应用时代,我们不需要花费时间去关心调用链路这个东西。但是链路跟踪不仅仅是在分布式场景下才会有,即使是单体应用,同样也会存在调用链路。例如,我们把应用中的每个服务接口作为一个链路节点,那么从请求进来到返回响应,把这个过程中多历经的所有的方法接口串联起来,就能组成一条完整的链路,如下图所示:

蚂蚁金服分布式链路跟踪组件 SOFATracer 总览 | 剖析_第1张图片

对于单体应用而言,如果访问一个资源没有成功,那么我们可以很快的锁定是哪一台机器,然后通过查询这台机器上的日志就能定位问题。

但是在微服务体系架构下,这种方式会显得非常无力。对于一个稍具规模的应用来说,一次请求可能会跨越相当多的服务节点,在这种情况下,如果一个请求没有得到成功的响应,就不能确定到底是哪个节点出了问题。

蚂蚁金服分布式链路跟踪组件 SOFATracer 总览 | 剖析_第2张图片

因此在面对这种复杂的大规模分布式集群来实现的服务体系来说,就需要一些可以帮助理解各个应用的线上调用行为、并可以分析远程调用的组件。

基于上述背景,蚂蚁金服开源了基于OpenTracing 规范 (http://opentracing.io/documentation/pages/spec.html)实现的 SOFATracer分布式链路跟踪组件,为实施大规模服务化体系架构场景下提供了链路跟踪的解决方案。

在介绍SOFATracer之前,先来了解一下Opentracing规范。

1、Opentracing 简介

首先来解释下OpenTracing 是什么OpenTracing致力于为分布式跟踪创建更标准化的API和工具,它由完整的API规范、实现该规范的框架、库以及项目文档组成。

OpenTracing 提供了一套平台无关、厂商无关的 API,这样不同的组织或者开发人员就能够更加方便的添加或更换追踪系统的实现。 OpenTracing API 中的一些概念和术语,在不同的语言环境下都是共享的。

1.1、数据模型

Opentracing规范中,一条trace链路是由多个与之关联的span组成,一条链路整体可以看做是一张有向无环图,各个span之间的边缘关系被称之为“References”。下面是官方提供的示例:

蚂蚁金服分布式链路跟踪组件 SOFATracer 总览 | 剖析_第3张图片

如果已时间轴维度来看的话,也可以表现为下面的形式(官方示例):

蚂蚁金服分布式链路跟踪组件 SOFATracer 总览 | 剖析_第4张图片

root span: 当前链路中的第一个span

ChildOf和FollowFrom是目前被定义的两种References类型

`ChildOf` : 父级 span某种程度上取决于子span (子span的结果可能会对父span产生影响)

`FollowFrom` :父 Span 不以任何方式依赖子 Span

但是为了简化span之间的这种依赖关系,在具体实现时通常会将具有嵌套关系的作为ChildOf,平行执行的作为FollowFrom,比如:

a、ChildOf 示例

在methodA中调用了methodB :

蚂蚁金服分布式链路跟踪组件 SOFATracer 总览 | 剖析_第5张图片

产生的span在时间维度上展现的视角如下:

这种关系一般会 表示为SpanB ChildOf SpanA。

b、FollowFrom 示例

method方法中,methodA执行之后methodB执行 :

产生的span在时间维度上展现的视角如下:

这种关系一般会 表示为SpanB FollowFrom SpanA。

1.2、API

Opentracing API是对分布式链路中涉及到的一些列操作的高度抽象集合。Opentracing中将所有核心的组件都声明为接口,例如Tracer、Span、SpanContext、Format(高版本中还包括Scope和ScopeManager)等。SOFATracer使用的版本是 0.22.0 ,主要是对Tracer、Span、SpanContext三个概念模型的实现。下面就针对这三个组件结合SOFATracer来分析。

1.3、SOFATracer 标准实现

下图为SOFATracer中对于这三个核心接口实现的类图结构:

蚂蚁金服分布式链路跟踪组件 SOFATracer 总览 | 剖析_第6张图片

由于篇幅原因,下面的介绍过程中一些点不会展开说明,有兴趣的同学可以自行官网查看完整的OpenTracing-api 规范(https://opentracing.io/specification/)。

a、Tracer & SofaTracer

Tracer是一个简单、广义的接口,它的作用就是构建span和传输span。核心接口列表如下:

蚂蚁金服分布式链路跟踪组件 SOFATracer 总览 | 剖析_第7张图片

SofaTracer实现了Tracer接口,并扩展了采样、数据上报等能力。

b、Span & SofaTracerSpan

Span是一个跨度单元,在实际的应用过程中,Span就是一个完整的数据包,其包含的就是当前节点所需要上报的数据。核心接口列表如下:

蚂蚁金服分布式链路跟踪组件 SOFATracer 总览 | 剖析_第8张图片

关于tags和log的解释:如果把从进入公司到离开公司这段时间作为一个span,那么tags里面可以是你写的代码,你喝的水,甚至你讲过的话;log则更关注某个时刻的事,比如在12:00 去吃了个饭,在15:00 开了个会。

如果说tags里面都是和公司有关的,那么Baggage里面则不仅仅是局限于你在公司的事,比如你口袋里的手机。

SofaTracerSpan在实现Span接口,并扩展了对Reference、tags、线程异步处理以及插件扩展中所必须的logType和产生当前span的Tracer类型等处理的能力。

c、SpanContext & SofaTracerSpanContext

SpanContext对于OpenTracing实现是至关重要的,通过SpanContext可以实现跨进程的链路透传,并且可以通过SpanContext中携带的信息将整个链路串联起来。

官方文档中有这样一句话:“在OpenTracing中,我们强迫SpanContext实例成为不可变的,以避免Span在finish和reference操作时会有复杂的生命周期问题。” 这里是可以理解的,如果SpanContext在透传过程中发生了变化,比如改了tracerId,那么就可能导致链路出现断缺。

SpanContext中只有一个接口:

蚂蚁金服分布式链路跟踪组件 SOFATracer 总览 | 剖析_第9张图片

SofaTracerSpanContext实现了SpanContext接口,扩展了构建SpanContext、序列化baggageItems以及SpanContext等新的能力,除此之外,SpanContext在跨进行透传时携带的信息进行了规范:

蚂蚁金服分布式链路跟踪组件 SOFATracer 总览 | 剖析_第10张图片

2、SOFATracer 扩展

为了满足在复杂场景下的链路跟踪需求,SOFATracer在Opentracing规范基础上又提供了丰富的扩展能力。

2.1、SOFATracer 架构及功能扩展

蚂蚁金服分布式链路跟踪组件 SOFATracer 总览 | 剖析_第11张图片

SOFATracer基于OpenTracing 规范(https://opentracing.io/specification/)实现,并且通过Disruptor(https://github.com/LMAX-Exchange/disruptor)组件实现了日志的无锁异步打印能力。

基于 SLF4J 的 MDC 扩展能力

应用在通过面向日志编程接口 SLF4J 打印应用日志时,可以只在对应的日志实现配置文件的 PatternLayout 中添加相应的参数即可,如添加 [%X{SOFA-TraceId},%X{SOFA-SpanId}] ,那么应用日志就可以在发生链路调用时打印出相应的 TraceId 和 SpanId ,而无论应用具体的日志实现是 Logback、Log4j2 或者 Log4j。关于这部分的实现原理,期待大家一起编写,领取方式见文末。

SOFATracer的埋点机制

SOFATracer目前仅提供了基于自身API埋点的方式。SOFATracer 中所有的插件均需要实现自己的 Tracer 实例,如 Mvc 的 SpringMvcTracer 、HttpClient 的 HttpClientTracer 等,如下图所示:

蚂蚁金服分布式链路跟踪组件 SOFATracer 总览 | 剖析_第12张图片

SOFATracer 将不同的扩展组件分为 AbstractClientTracer 和 AbstractServerTracer,再通过AbstractClientTracer 和 AbstractServerTracer 衍生出具体的组件 Tracer 实现。这种方式的好处在于,所有的插件实现均有 SOFATracer 本身来管控,对于不同的组件可以轻松的实现差异化和定制化。

但是为了能够拥抱社区,我们在后续的版本中将会提供基于Opentracing API的埋点扩展实现,从而实现与opentracing-contrib的无缝对接。基于Opentracing API的插件埋点方案如下图所示:

蚂蚁金服分布式链路跟踪组件 SOFATracer 总览 | 剖析_第13张图片

关于SOFATracer基于特有API埋点的实现以及如何实现对接OT-api埋点,期待大家一起编写,领取方式见文末。

SOFATracer的数据上报机制

SOFATracer中并没有将不同的Reporter设计成不同的策略,然后根据不同的策略来实现具体的上报操作,而是使用了一种类似组合的方式,并且在执行具体上报的流程中通过参数来调控是否执行具体的上报。

蚂蚁金服分布式链路跟踪组件 SOFATracer 总览 | 剖析_第14张图片

image.png | center | 306x514

从流程图中可以看到,此过程中涉及到了三个上报点,首先是上报到zipkin,后面是落盘;在日志记录方面,SOFATracer中为不同的组件均提供了独立的日志空间,除此之外,SOFATracer在链路数据采集时提供了两种不同的日志记录模式:摘要日志和统计日志,这对于后续构建一些如故障的快速发现、服务治理等管控端提供了强大的数据支撑。关于数据上报,期待大家一起编写,领取方式见文末。

SOFATracer的采样机制

对于链路中的数据,并非所有的数据都是值得关注的。一方面是可以节约磁盘空间,另一方面可以将某些无关数据直接过滤掉。基于此,SOFATracer提供了链路数据采样能力。目前我们提供了两种策略,一种是基于固定比率的采样,另一种是基于用户扩展实现的自定义采样;在自定义采样设计中,我们将SofaTracerSpan实例作为采样计算的条件,用户可以基于此实现丰富的采样规则。关于采样机制,期待大家一起编写,领取方式见文末。

SOFATracer链路透传机制

关于透传机制,我们不仅需要考虑线程内传递,还需要考虑跨线程以及异步线程场景,对于分布式链路来说,最核心还有如何实现跨进程的数据透传。关于SOFATracer链路透传 以及OpenTracing新规范中对线程传递的支持,期待大家一起编写,领取方式见文末。

2.2、SOFATracer RoadMap

首先介绍下目前 SOFATracer 的现状和一些正在做的事情。

蚂蚁金服分布式链路跟踪组件 SOFATracer 总览 | 剖析_第15张图片

SOFATracer 版本说明:

3.x 版本支持webflux等,基于分支发布。

2.x 版本基于master发布,目前版本是 2.3.0 。

欢迎对相关功能和feature有兴趣的同学,一起参与开发~

3、欢迎加入,参与 SOFATracer 源码解析

本文作为《剖析 |SOFATracer组件系列》第一篇,主要还是希望大家对 SOFATracer 组件有一个认识和了解,之后,我们会逐步详细介绍每部分的代码设计和实现,预计会按照如下的目录进行:

分布式链路跟踪组件 SOFATracer 概述

SOFATracer数据上报机制和源码分析

SOFATracer API组件埋点机制和源码分析

SOFATracer链路透传原理与SLF4J MDC的扩展能力分析

SOFATracer的采样策略和源码分析

如果有同学对以上某个主题特别感兴趣的,可以留言讨论,我们会适当根据大家的反馈调整文章的顺序,谢谢大家关注 SOFA ,关注 SOFATracer,我们会一直与大家一起成长的。

领取方式:

关注公众号:金融级分布式架构(Antfin_SOFA),后台回复想认领的文章名称,我们将会主动联系你,确认资质后,即可加入,It's your show time!

除了源码解析,也欢迎提交 issue 和 PR:

SOFATracerhttps://github.com/alipay/sofa-tracer

公众号:金融级分布式架构(Antfin_SOFA)

你可能感兴趣的:(蚂蚁金服分布式链路跟踪组件 SOFATracer 总览 | 剖析)