目录
一、简介
分布式系统由于分别部署在不同的服务器上,服务之间的调用关系相比单体应用来说不是显而易见,另外各个服务之间的响应时间也是优化,排故的重要信息。因此,需要一套链路跟踪机制,springCloud基于zipkin提供了一套链路跟踪功能,但是我们想更灵活,可以加入自己需要的信息,新增跟踪点,控制细粒度。这样的话,我们可以自己实现一套链路跟踪功能。准备通过如下七篇文章来说说怎么实现自己的链路跟踪器。另外springCloud提供的zipkin的链路跟踪可以查看这篇文章《spring-cloud 分布式日志采集》
《springCloud微服务系列——链路跟踪第一篇——设计思路以及通用链路跟踪器》
《springCloud微服务系列——链路跟踪第二篇——mvc链路跟踪器》
《springCloud微服务系列——链路跟踪第三篇——feign链路跟踪器》
《springCloud微服务系列——链路跟踪第四篇——hystrix链路跟踪器》
《springCloud微服务系列——链路跟踪第五篇——mybatis链路跟踪器》
《springCloud微服务系列——链路跟踪第六篇——redis缓存链路跟踪器》
二、思路
我们先看一下基本概念
基本概念
-
traceId
traceId是一次链路跟踪的唯一标识
-
rpcId
rpcId表示调用层级关系,类似于1.1.2这种形式
主体思路
先说一下存储,存储还是存在Elasticsarch中
核心思路:
- 请求开始的时候,生成一个traceId。这个时候rpcId为1。我们把该信息存储到线程安全的地方。
- 每一个需要跟踪的地方被调用,从当前线程中获取链路跟踪信息,将层级加深,比如1.1
- 层级加深的时候,我们需要判断是第一次进入该层次,比如加深后为1.1.1,还是第n次进入该层次,比如加深后为1.1.(n+1)。因此我们需要缓存每一层的最大序列号,加深的时候查一下下一层的最大序列号n,没有则为0,我们就可以获得加深后的序列号为(n+1)
- 每次调用完毕将层级降级,比如从1.1.1降到1.1(你可能已经注意到,从1.1降级怎么办?是1还是1.0,我们用1.0,详细的 情况我们后面再说)
我们可以看到,整个思路看上起和堆栈类似,先进后出。
线程安全
整个链路跟踪的时候我们会储存当前链路信息,为了跨实例获得信息,我们会存储在静态变量中。另外,有些操作也会产生新线程,比如hystrix熔断,很显然我们需要考虑线程安全的问题。我们可以通过ThreadLocal来进行保存。
层级细节处理