seluth
原理
1.Dapper
- Dapper相较之前的其他的tracing system而言主要的区别有:
使用抽样方法来达到low-overhead,Sleuth在实现的时候采用的是水塘抽样。
使用上的透明度:Sleuth基本做到了在开发人员无感知的情况下,收集链路信息。
- Dapper的架构主要包括了:tree,span,annoatation。
一个tree由1个或多个span组成
一个span是dapper里面的最基本的单位,一个span里面包含了一个span开始和结束的时间戳。我们可以把span理解为一对请求和返回。所以span是会成对出现的。同时span里面还包括了parent span id和trace id。所以我们可以通过这些信息来构造出完整的链路并且恢复有序的调用关系。
因为span中记录的时间戳是来自于client或者不同的server,所以时间同步也是需要注意的一点。
- Trace信息如何透传
在Dapper的论文里面和网上看到阿里的Eagle Eye都是通过threadLocal来实现的全局链路跟踪,就决定去研究一下threaLocal的工作原理。
总的来说,调用会有两种情况:
线程/进程间的调用,例如:RPC,http,异步。
线程内的调用。
- 在Dapper里面:
线程间的调用使用参数传递
线程内的调用使用ThreadLocal传递
线程间参数透传的方法:
HTTP: 通过header来透传trace信息
RPC: 通过自定义RPC协议
总的来说还是通过参数透传,这个可以通过修改通用库来实现无感知的透传。
线程内参数透传的方法:
ThreadLocal
ThreadLocal其实是一个线程的局部变量,会和一个线程同生共死。通过ThreadLocal创建的变量只能被当前线程访问修改。
进入线程时,将Trace信息存储在ThreadLocal变量中,出线程时,从ThreadLocal变量中取出Trace信息,作为参数传递到下一个线程。
2.seluth
- web环境下的sleuth执行原理:
首先sleuth创建TraceFilter,对所有的网络请求进行拦截,如果请求的header中没有span信息,则创建Span对象,生成span id、trace id等,如果header中有,则直接使用header中的数据创建Span对象,之后将span id、trace id设置到sl4j的MDC中。
- RestTemplate发送请求时的sleuth执行原理:
RestTemplateInterceptorInjector拦截器对请求拦截,将新生成的span id、trace id等信息设置到请求的header中。这样服务端收到请求后就可以从header中解析出Span信息
数据结构
1614333302(1).jpg基于HTTP请求的数据传递两种方式的数据结构:一种是,另一种是做为头信息传递
1.做为头信息传递 Request Header
spanid:一个工作单元(rpc 调用)的唯一标识。
parentspanid:当前工作单元的上一个工作单元,Root Span(请求链路的第一个工作单元)的值为空。
traceid:一条请求链条(trace) 的唯一标识。
sampled:是否被抽样为输出的标志,1 为需要被输出,0 为不需要被输出。
2.做为参数传递
Sleuth 会把跟踪数据 (appname、traceId、spanId、exportable) 添加到 Slf4J MDC
MDC 的实现实际是将需要记录到日志的信息设置到当前线程的上下文(ThreadContext)中。
MDC 中的信息:[appname,traceId,spanId,exportable]
appname:应用名称,即 spring.application.name 的值。
tranceId:整个请求链路的唯一ID。
spanId:基本的工作单元,一个 RPC 调用就是一个新的 span。启动跟踪的初始 span 称为 root span ,此 spanId 的值与 traceId 的值相同。
exportable:是否将数据导入到 Zipkin 中,true 表示导入成功,false 表示导入失败
3.其他参数
Trace:它是由一组有相同Trace ID的Span串联形成一个树状结构。为了实现请求跟踪,当请求请求到分布式系统的入口端点时,只需要服务跟踪框架为该请求创建一个唯一的跟踪标识(即前文提到的Trace ID),同时在分布式系统内部流转的时候,框架始终保持传递该唯一标识,直到返回请求为止,我们通过它将所有请求过程中的日志关联起来;
Span:它代表了一个基础的工作单元,例如服务调用。为了统计各处理单元的时间延迟,当前请求到达各个服务组件时,也通过一个唯一标识(即前文提到的Span ID)来标记它的开始、具体过程以及结束。通过span的开始和结束的时间戳,就能统计该span的时间延迟,除此之外,我们还可以获取如事件名称、请求信息等元数据。
Annotation:它用于记录一段时间内的事件。内部使用的最重要的注释是:
cs - Client Sent - 客户端发送一个请求,这个注解描述了这个Span的开始。
sr - Server Received - 服务端获得请求并准备开始处理它,其中(sr – cs) 时间戳便可得到网络传输的时间。
ss - Server Sent (服务端发送响应)– 该注解表明请求处理的完成(当请求返回客户端), (ss – sr)时间戳就可以得到服务器请求的时间。
cr - Client Received (客户端接收响应)- 表明此时Span的结束,(cr – cs)时间戳便可以得到整个请求所消耗的时间。
使用
1.Spring Cloud Sleuth可以追踪以下类型的组件:
async
hystrix
messaging
websocket
rxjava
scheduling
web(SpringWebMvc,Spring WebFlux, Servlet)
webclient(Spring RestTemplate)
feign
zuul
zipkin
Zipkin的基础架构,它主要由4个核心组件构成:
1614333203(1).jpg
Collector(收集器组件):主要负责收集外部系统跟踪信息,转化为Zipkin内部的Span格式。
Storage(存储组件):主要负责收到的跟踪信息的存储,默认为存储在内存中,同时支持存储到Mysql、Cassandra以及ElasticSearch。
API(Query): 负责查询Storage中存储的数据,提供简单的JSON API获取数据,主要提供给web UI使用。
Web UI(展示组件):提供简单的web界面,方便进行跟踪信息的查看以及查询,同时进行相关的分析。
zipkin+seluth的使用
spring cloud sleuth可以结合zipkin,将信息发送到zipkin,利用zipkin的存储来存储信息,利用zipkin ui来展示数据。同时也可以只是简单的将数据记在日志中。
sleuth+log:这种方式只需要引入jar包(Maven中加入spring-cloud-starter-sleuth依赖)即可
sleuth+zipkin+http:sleuth收集跟踪信息通过http请求发给zipkin。这种需要启动一个zipkin,zipkin用来存储数据和展示数据。zipkin如果不配置存储的话,默认是在内存中的。如果存储在内存中,当重启应用后,数据就会丢失了
sletuh+streaming+zipkin:这种方式通过spring cloud streaming将追踪信息发送到zipkin。spring cloud streaming目前只支持kafka和rabbitmq。Zipkin Collector从消息中间件中读取数据并存储。
网友评论