SOFA Scalable Open Financial Architecture 是蚂蚁金服自主研发的金融级分布式中间件,包含了构建金融级云原生架构所需的各个组件,是在金融场景里锤炼出来的最佳实践。
SOFATracer 是一个用于分布式系统调用跟踪的组件,经过统一的 TraceId 将调用链路中的各类网络调用状况以日志的方式记录下来,以达到透视化网络调用的目的,这些链路数据可用于故障的快速发现,服务治理等。 SOFAT racer :https://github.com/alipay/sofa-tracer
本文为《剖析 | SOFATracer 框架》第一篇。《剖析 | SOFASOFATracer 框架》系列由 SOFA 团队和源码爱好者们出品, 项目代号:<SOFA:TracerLab/>,文章尾部有参与方式,欢迎一样对源码热情的你加入html
在单体应用时代,咱们不须要花费时间去关心调用链路这个东西。可是链路跟踪不只仅是在分布式场景下才会有,即便是单体应用,一样也会存在调用链路。例如,咱们把应用中的每一个服务接口做为一个链路节点,那么从请求进来到返回响应,把这个过程当中多历经的全部的方法接口串联起来,就能组成一条完整的链路,以下图所示:git
SOFATracer
分布式链路跟踪组件,为实施大规模服务化体系架构场景下提供了链路跟踪的解决方案。
SOFATracer
以前,先来了解一下
Opentracing
规范。
首先来解释下 OpenTracing
是什么 OpenTracing
致力于为分布式跟踪建立更标准化的API和工具,它由完整的API规范、实现该规范的框架、库以及项目文档组成。github
OpenTracing
提供了一套平台无关、厂商无关的
API
,这样不一样的组织或者开发人员就可以更加方便的添加或更换追踪系统的实现。
OpenTracingAPI
中的一些概念和术语,在不一样的语言环境下都是共享的。
Opentracing
规范中,一条
trace
链路是由多个与之关联的
span
组成,一条链路总体能够看作是一张有向无环图,各个
span
之间的边缘关系被称之为“
References
”。下面是官方提供的示例:
可是为了简化root span
: 当前链路中的第一个span
ChildOf
和FollowFrom
是目前被定义的两种References
类型ChildOf
: 父级 span某种程度上取决于子span (子span的结果可能会对父span产生影响)
FollowFrom
: 父Span
不以任何方式依赖子Span
span
之间的这种依赖关系,在具体实现时一般会将具备嵌套关系的做为
ChildOf
,平行执行的做为
FollowFrom
,好比:
methodA
中调用了
method
B :
span
在时间维度上展示的视角以下:
SpanBChildOfSpanA
。
method
方法中,
methodA
执行以后
methodB
执行 :
span
在时间维度上展示的视角以下:
SpanBFollowFromSpanA
。
OpentracingAPI
是对分布式链路中涉及到的一些列操做的高度抽象集合。
Opentracing
中将全部核心的组件都声明为接口,例如
Tracer
、
Span
、
SpanContext
、
Format
(高版本中还包括
Scope
和
ScopeManager
)等。
SOFATracer
使用的版本是 0.22.0 ,主要是对
Tracer
、
Span
、
SpanContext
三个概念模型的实现。下面就针对这三个组件结合
SOFATracer
来分析。
SOFATracer
中对于这三个核心接口实现的类图结构:
a、Tracer & SofaTracer因为篇幅缘由,下面的介绍过程当中一些点不会展开说明,有兴趣的同窗能够自行官网查看完整的 OpenTracing-api 规范 (opentracing.io/specificati…)。web
Tracer
是一个简单、广义的接口,它的做用就是构建
span
和传输
span
。核心接口列表以下:
接口 | 描述 |
---|---|
SpanBuilder buildSpan(String operationName) | 根据指定的operationName构建一个新的span |
void inject(SpanContext spanContext, Formatformat, C carrier); | 将 spanContext 以 format 的格式注入到 carrier 中 |
SpanContext extract(Format format, C carrier); | 以 format 的格式从carrier中解析出 SpanContext |
SofaTracer
实现了
Tracer
接口,并扩展了采样、数据上报等能力。
Span
是一个跨度单元,在实际的应用过程当中,
Span
就是一个完整的数据包,其包含的就是当前节点所须要上报的数据。核心接口列表以下:
接口 | 描述 |
---|---|
SpanContext context() | 从 span 中获取 SpanContext |
void finish()/void finish(long finishMicros) | 结束一个 span |
void close() | 关闭 span |
Span setTag(String key, value) | 设置 tags |
Span log(long timestampMicroseconds, String event) | 设置 log 事件 |
Span setOperationName(String operationName) | 设置span的operationName |
Span setBaggageItem(String key, String value) | 设置 BaggageItem |
String getBaggageItem(String key) | 获取 BaggageItem |
关于
tags
和log
的解释:若是把从进入公司到离开公司这段时间做为一个span
,那么tags
里面能够是你写的代码,你喝的水,甚至你讲过的话;log
则更关注某个时刻的事,好比在12:00 去吃了个饭,在15:00 开了个会。 若是说tags
里面都是和公司有关的,那么Baggage
里面则不只仅是局限于你在公司的事,好比你口袋里的手机。编程
SofaTracerSpan
在实现
Span
接口,并扩展了对
Reference
、
tags
、线程异步处理以及插件扩展中所必须的
logType
和产生当前
span
的
Tracer
类型等处理的能力。
SpanContext
对于
OpenTracing
实现是相当重要的,经过
SpanContext
能够实现跨进程的链路透传,而且能够经过
SpanContext
中携带的信息将整个链路串联起来。
官方文档中有这样一句话:“在
OpenTracing
中,咱们强迫SpanContext
实例成为不可变的,以免Span
在finish
和reference
操做时会有复杂的生命周期问题。” 这里是能够理解的,若是SpanContext
在透传过程当中发生了变化,好比改了tracerId
,那么就可能致使链路出现断缺。api
SpanContext
中只有一个接口:
接口 | 描述 |
---|---|
Iterable> baggageItems(); | 拿到全部的baggageItems 透传数据 |
SofaTracerSpanContext
实现了
SpanContext
接口,扩展了构建
SpanContext
、序列化
baggageItems
以及
SpanContext
等新的能力,除此以外,
SpanContext
在跨进行透传时携带的信息进行了规范:
携带信息 | 描述 |
---|---|
traceId | 全链路惟一的标识信息 |
spanId | spanId |
parentId | 父 spanId |
isSampled | 采样标记 |
sysBaggage | 系统透传数据 |
bizBaggage | 业务透传数据 |
为了知足在复杂场景下的链路跟踪需求, SOFATracer
在 Opentracing
规范基础上又提供了丰富的扩展能力。网络
SOFATracer
基于
OpenTracing 规范
(
opentracing.io/specificati…
)实现,而且经过
Disruptor
(
github.com/LMAX-Exchan…
)组件实现了日志的无锁异步打印能力。
基于 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
将不一样的扩展组件分为
AbstractClientTracer
和
AbstractServerTracer
,再经过
AbstractClientTracer
和
AbstractServerTracer
衍生出具体的组件
Tracer
实现。这种方式的好处在于,全部的插件实现均有
SOFATracer
自己来管控,对于不一样的组件能够轻松的实现差别化和定制化。
OpentracingAPI
的埋点扩展实现,从而实现与
opentracing-contrib
的无缝对接。基于
OpentracingAPI
的插件埋点方案以下图所示:
SOFATracer
基于特有
API
埋点的实现以及如何实现对接
OT-api
埋点,期待你们一块儿编写,领取方式见文末。
SOFATracer
的数据上报机制
SOFATracer
中并无将不一样的
Reporter
设计成不一样的策略,而后根据不一样的策略来实现具体的上报操做,而是使用了一种相似组合的方式,而且在执行具体上报的流程中经过参数来调控是否执行具体的上报。
zipkin
,后面是落盘;在日志记录方面,
SOFATracer
中为不一样的组件均提供了独立的日志空间,除此以外,
SOFATracer
在链路数据采集时提供了两种不一样的日志记录模式:摘要日志和统计日志,这对于后续构建一些如故障的快速发现、服务治理等管控端提供了强大的数据支撑。关于数据上报,期待你们一块儿编写,领取方式见文末。
对于链路中的数据,并不是全部的数据都是值得关注的。一方面是能够节约磁盘空间,另外一方面能够将某些无关数据直接过滤掉。基于此,SOFATracer
的采样机制
SOFATracer
提供了链路数据采样能力。目前咱们提供了两种策略,一种是基于固定比率的采样,另外一种是基于用户扩展实现的自定义采样;在自定义采样设计中,咱们将
SofaTracerSpan
实例做为采样计算的条件,用户能够基于此实现丰富的采样规则。关于采样机制,期待你们一块儿编写,领取方式见文末。
关于透传机制,咱们不只须要考虑线程内传递,还须要考虑跨线程以及异步线程场景,对于分布式链路来讲,最核心还有如何实现跨进程的数据透传。关于SOFATracer
链路透传机制
SOFATracer
链路透传 以及
OpenTracing
新规范中对线程传递的支持,期待你们一块儿编写,领取方式见文末。
SOFATracer
的现状和一些正在作的事情。
SOFATracer
版本说明:
3.x 版本支持欢迎对相关功能和webflux
等,基于分支发布。
2.x 版本基于master
发布,目前版本是 2.3.0 。
feature
有兴趣的同窗,一块儿参与开发~
本文做为《剖析 | SOFATracer
组件系列》第一篇,主要仍是但愿你们对 SOFATracer
组件有一个认识和了解,以后,咱们会逐步详细介绍每部分的代码设计和实现,预计会按照以下的目录进行:架构
SOFATracer
概述【已完成】SOFATracer
数据上报机制和源码分析【待领取】SOFATracerAPI
组件埋点机制和源码分析【待领取】SOFATracer
链路透传原理与 SLF4J MDC
的扩展能力分析【待领取】SOFATracer
的采样策略和源码分析【待领取】SOFA
,关注
SOFATracer
,咱们会一直与你们一块儿成长的。
除了源码解析,也欢迎提交 issue 和 PR: SOFATracer:https://github.com/alipay/sofa-tracer框架
长按关注,获取分布式架构干货异步
欢迎你们共同打造 SOFAStack https://github.com/alipay