由于微服务很复杂,当服务多了之后,就需要有一个东西去记录服务之间的调用,这样可以快速定位问题,且最好能同时记录服务之间的调用时长等信息,方便优化系统。spring cloud sleuth就有这样的作用。我们称这种技术叫做服务链路追踪
sleuth记录服务链路主要是依靠日志
2020-05-08 14:39:31.429 INFO [sleuth-track2,8f38aeed036ff375,21f05063bd635c35,false] 9236 --- [nio-8083-exec-1] c.t.c.s.controller.Controller : hello track2
我在上面随便打印了一条它追踪日志,它在打印日志时,主要有这么几个组成部分:
第一个值:sleuth-track2,它记录了应用的名称,即spring.application.name
第二个值:8f38aeed036ff375,spring cloud sleuth生成的一个id,成为trace Id,它用来标识一条请求链路,一条请求链路包含一个Track Id,多个Span Id。一条服务链路上的track id是相同的
第三个值:21f05063bd635c35,spring cloud sleuth生成的另外一个id,成为span id,它表示一个基本的工作单元,比如发送一个http请求
第四个值:false ,表示是否要将该信息输出到Zipkin等服务中来收集和展示
创建3个项目:服务注册中心,sleuth-track1,sleuth-track2
服务注册中心就不说了,大致思路就是sleuth-track1使用feign调用sleuth-track2,然后我们打印个日志看下,服务之间的调用部分也不展示了
给sleuth-track1,sleuth-track2添加如下依赖即可
org.springframework.cloud
spring-cloud-starter-sleuth
调用sleuth-track1中的controller接口,然后该接口会使用feign调用sleuth-track2的接口,
注意:打印信息一定要使用log,不能用System.out.print,因为sleuth是基于log日志才操作的
sleuth-track1:
2020-05-08 15:22:42.515 INFO [sleuth-track1,2c1215ce5b940d18,2c1215ce5b940d18,false] 14632 --- [nio-8082-exec-3] c.t.c.sleuthtack1.controller.Controller : hello track1
sleuth-track2:
2020-05-08 15:22:42.553 INFO [sleuth-track2,2c1215ce5b940d18,2900b3e2e12a1326,false] 9236 --- [nio-8083-exec-6] c.t.c.s.controller.Controller : hello track2
会发现他们的track id是相同的,span id是不同的
主要包括两个关键点
在spring boot应用中,通过在工程中引入spring-cloud-starter-sleuth依赖后,它会自动为当前应用构建各通信通道的追踪机制
比如:
实现追踪就是在请求的请求头上添加实现追踪需要的重要信息。
zipkin分为服务端和客户端,zipkin server负责接受client传过来的数据,然后进行数据的处理与展示
zipkin client就是发送数据的
这里我们使用spring boot 1.5.8.RELEASE,spring cloud Dalston.SR4版本来写项目,版本问题引发的bug会在下面说明
io.zipkin.java
zipkin-server
io.zipkin.java
zipkin-autoconfigure-ui
在启动类上添加注解@EnableZipkinServer
server:
port: 9411
spring:
application:
name: zipkin-server
启动项目,并访问http://localhost:9411/
这个其实就是能产生追踪日志的客户端,spring cloud 的项目基本上都算是zipkin client,比如我们上面创建的sleuth-track1和sleuth-track2。
org.springframework.cloud
spring-cloud-starter-sleuth
org.springframework.cloud
spring-cloud-sleuth-zipkin
#指定zipkin服务器的url地址
spring:
zipkin:
base-url: http://localhost:9411
在第2节的时候,其中有个属性打印出来是false,该属性是表示是否要将该信息输出到Zipkin等服务中来收集和展示。
该属性的作用是抽样收集:理论上讲我们收集的追踪信息是越多越好,但是在高并发的分布式系统中,大量的请求调用会产生海量的追踪日志信息,如果过多的收集这些信息,会对整个系统的性能造成一定影响。所以我们要指定抽样收集
可通过配置来修改你的收集百分比:
spring.sleuth.sampler.percentage=0.1
默认值就是0.1,代表收集10%的请求追踪信息。
当我们本地调试时,可以设置为1,表示收集全部的追踪信息
要确保您的应用程序名称在Zipkin中正确显示,请在bootstrap.yml中设置spring.application.name属性
我一开始使用的spring cloud 版本:Hoxton.SR3,springboot版本:2.2.6.RELEASE,通过父pom中进行版本管理的,zipkin server和zipkin client都是其子模块。
zipkin server端:
当我引入zipkin-server和zipkin-autoconfigure-ui依赖时,pom文件直接报错,说找不到依赖,我一开始以为是没有指定zipkin版本的问题(我看书上写的也没指定版本),所以我就引入了zipkin的当前最高的一个版本号,就没有报错了,
接着启动,启动报错说是log框架太多了,导致启动失败,然后我查看了以下版本依赖,spring boot 默认使用的是log back,而zipkin默认使用的是log4j,然后我就在zipkin server的依赖中去除了它自己的日志框架。
再次启动,还是报错,说是tomcat embed什么玩意又不对了,然后搞了半天(主要是想降低tomcat版本,结果boot2.x降版本不好搞,会出问题),还是没搞对,我就放弃了。
但是,终究还是要搞的,我就只能按照书上的版本试,重新创建了一个项目(之前我是通过maven的父pom来继承的)降低springboot(1.5.22.RELEASE)和springcloud(Brixton.SR5)版本,再次引入zipkin的依赖,发现就算不写版本号都没啥问题了。
zipkin client 端:
注意我的zipkin client是继承的父pom文件,依赖的高版本的springboot和spring cloud
zipkin-client是按官方文档要求搞的:依赖的spring-cloud-starter-zipkin包,并进行正常配置。启动没有报错,但是在zipkin client向zipkin server自动发送数据请求时,报错了:大致就是说访问/api/v2/spans接口时报404。我分析一下报错原因:
zipkin server方面由于是没有指定zipkin版本号(跟着spring boot 的版本走的),所以它自动导入的版本是io.zipkin.java:zipkin:1.28.0(注意这个serer项目的springboot版本是低于2的)
zipkin client方面:由于我这个项目跟着父pom走的,所以spring boot版本是大于2的,这样导致了我在依赖的时候并不是像boot2以前的版本那样去依赖spring-cloud-starter-sleuth和spring-cloud-sleuth-zipkin包来激活zipkin,而是通过spring-cloud-starter-zipkin依赖包来激活zipkin的。
而spring-cloud-starter-zipkin这个包它依赖的zipkin的版本是:io.zipkin.zipkin2:zipkin:2.19.3,仔细观察下绿色的字的不同,会发现,zipkin server这个springboot2以前版本依赖的zipkin包相比于springboot2之后依赖的zipkin包少了个2,关键就在这里了。
io.zipkin.java:zipkin:1.28.0因为没有2所以我们简称v1版本,io.zipkin.zipkin2:zipkin:2.19.3我们简称v2版本。
导入v1版本的zipkin后,通过项目启动的mapping映射关系可以看出它里面的api都是/api/v1。。。
导入v2版本的zipkin可以发现,它里面的api是/api/v2。。。
所以结果就出来了,由于zipkin server依赖的zipkin和zipkin client依赖的zipkin 大版本是不一样的,所以就出现了404的问题。
宗旨就是让zipkin server和zipkin client的zipkin大版本要相同,要么都是io.zipkin.java,要么都是io.zipkin.zipkin2
如果你的项目是spring boot1.x (<2):
如果你的项目是spring boot 2.x (>2):
不要试图通过降低zipkin client 端的spring-cloud-starter-sleuth和spring-cloud-sleuth-zipkin依赖包的版本来解决这个bug,因为这些我都试过了,不起作用,会出现其他bug
注意spring cloud版本要和spring boot版本对应,否则会出现很多问题: