SpringCloud Sleuth工作原理和源码分析


 

  1.  工作原理
  2. 源码分析

 

 

术语(Terminology)

  • Span:基本工作单元,例如,在一个新建的span中发送一个RPC等同于发送一个回应请求给RPC,span通过一个64位ID唯一标识,trace以另一个64位ID表示,span还有其他数据信息,比如摘要、时间戳事件、关键值注释(tags)、span的ID、以及进度ID(通常是IP地址),span在不断的启动和停止,同时记录了时间信息,当你创建了一个span,你必须在未来的某个时刻停止它。
  • Trace:一系列spans组成的一个树状结构,例如,如果你正在跑一个分布式大数据工程,你可能需要创建一个trace。
  • Annotation:用来及时记录一个事件的存在,一些核心annotations用来定义一个请求的开始和结束
    •   cs - Client Sent -客户端发起一个请求,这个annotion描述了这个span的开始
    •   sr - Server Received -服务端获得请求并准备开始处理它,如果将其sr减去cs时间戳便可得到网络延迟
    •   ss - Server Sent -注解表明请求处理的完成(当请求返回客户端),如果ss减去sr时间戳便可得到服务端需要的处理请求时间
    •   cr - Client Received -表明span的结束,客户端成功接收到服务端的回复,如果cr减去cs时间戳便可得到客户端从服务端获取回复的所有所需时间

将Span和Trace在一个系统中使用Zipkin注解的过程图形化:

 

每个颜色的注解表明一个span(总计7个spans,从A到G),如果在注解中有这样的信息:

Trace Id = X

Span Id = D

Client Sent

这就表明当前span将Trace-Id设置为X,将Span-Id设置为D,同时它还表明了ClientSent事件。

spans 的parent/child关系图形化

 

实现分析

 

  • 服务本身对traceId的处理

    Sleuth通过Filter的方式,在filter中对请求头的处理来实现traceId的追踪。

     

    先判断http头中是否存在“X-B3-TraceId”,不存在,则生成新的traceId;存在,则以头X-B3-TraceId的值作为traceId。最后将X-B3-TraceId的值放到MDC中,以便日志输出中带上X-B3-TraceId。这样使得在本服务中,用户请求产生的日志输出都会带有traceId。

  • 服务间对traceId的处理

    在微服务中,服务A向服务B发起调用请求。那如何将A中的traceId传递给B呢?首先,先要了解服务A是如何调用服务B的。

    1、网关接收到进行,进行请求转发

  • 网关(gateway)TraceWebFilter

  •  

    网关(zuul)ZuulFilter(TracePostZuulFilter)中将traceId添加到http头X-B3-TraceId中,以便所转发请求对应的服务能从头中获取到traceId。同时还将traceId放到MDC中,以便本应用在输出日志时带traceId。

    2、服务内部通过feign注解调用另一个服务

    由于feign注解的实现是通过生成Hystrix的代理类来完成请求的处理,而Hystrix在进行请求发送时是通过异步的方式调用ribbon的组件进行负载均衡,然后通过Feign.Client的execute方法来进行请求的发送。故此时需要解决以下两个问题:

    (1)如何在异步线程中传递traceId。

    Sluth是通过实现HystrixConcurrencyStrategy接口来解决traceId异步传递的问题。Hystrix在实际调用时,会调用HystrixConcurrencyStrategy的wrapCallable方法。因此,通过实现这个接口,在wrapCallable中将traceId存放起来(具体参见SleuthHystrixConcurrencyStrategy)。

    (2)Feign如何在服务中传递traceId。

    Sluth通过实现Feign.Client,在execute前将traceId存放到X-B3-TraceId头中来实现(具体参见TraceFeignClient)。

 

日志中字段说明

2019-05-20 13:56:14.921 DEBUG [user-client,fdf23ab0a44d64d9,fdf23ab0a44d64d9,true] 15208 --- [nio-8033-exec-8] o.s.web.servlet.DispatcherServlet        : Completed 200 OK
2019-05-20 13:56:14.958 DEBUG [user-client,6b7be2e8ac041461,6b7be2e8ac041461,false] 15208 --- [io-8033-exec-10] o.s.web.servlet.DispatcherServlet        : GET "/favicon.ico", parameters={}

 

注意MDC中的[appname,traceId,spanId,exportable]:

  • spanId - the id of a specific operation that took place
  • appname - the name of the application that logged the span
  • traceId - the id of the latency graph that contains the span
  • exportable - whether the log should be exported to Zipkin or not. Whenwould you like the span not to be exportable? In the case in which you want towrap some operation in a Span and have it written to the logs only. 是否应该将日志导出到Zipkin

 

 

Sleuth 支持可追踪的组件包含:

 

 详细实现:

 

 

 

 

常见问题:

  1. Sleuth在异步线程中丢失traceId  TraceableExecutorService 包装 ExecutorService  http://www.saily.top/2018/12/29/sleuth-lost-traceId/

 

参考文档:

https://cloud.spring.io/spring-cloud-static/spring-cloud-sleuth/2.1.0.RELEASE/single/spring-cloud-sleuth.html#creating-spans-with-explicit-parent

https://github.com/apache/incubator-zipkin-b3-propagation#sampling-state-1

https://blog.csdn.net/yaowwwww7071/article/details/85769505

https://blog.csdn.net/xichenguan/article/details/77448288

https://blog.csdn.net/u010257992/article/details/52474639

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM