微服务架构是通过业务来划分服务,各个服务之间使用REST调用。对于复杂的业务可能需要很多个服务协同才能完成某个业务功能,如下图所示:
如果调用链路上任何一个服务出现问题或者网络超时,都会导致接口调用失败。随着业务的不断扩张,服务之间互相调用会越来越复杂,程序出现任何问题都少不了查看日志。由于调用关系非常复杂,导致日志排查困难。
分布式链路追踪就是要解决多个服务调用导致日志排查困难的问题,它可以将一个完整的调用链整合为一个完整有序的日志,然后根据时间排序就可以清晰的看到这个业务中全部日志以及执行顺序,从而轻松定位问题。
Spring Cloud Sleuth是Spring Cloud体系中的一个模块,用于在整个分布式系统中跟踪一个用户请求的过程(包括数据采集,数据传输,数据存储,数据分析,数据可视化)。捕获这些跟踪数据,就能构建微服务的整个调用链的视图,这是调试和监控微服务的关键工具。
Spring Cloud Sleuth有4个特点:
特点 | 说明 |
---|---|
提供链路追踪 | 通过sleuth可以很清楚的看出一个请求经过了哪些服务, 可以方便的理清服务间的调用关系 |
性能分析 | 通过sleuth可以很方便的看到每个请求的耗时,分析出哪些服务调用比较耗时,当服务调用耗时随着请求量的增大而增大时,也可以对服务的扩容提供一定的提醒作用 |
数据分析优化链路 | 对于频繁地调用一个服务,或者并行地调用等, 可以针对业务做一些优化措施 |
可视化 | 对于程序未捕获的异常,可以在zipkpin界面上看到 |
Zipkin是一个开放源代码的分布式跟踪系统,每个服务向zipkin报告计时数据,zipkin会根据调用关系通过Zipkin UI生成依赖关系图。github地址:https://github.com/openzipkin/zipkin
Zipkin提供了可插拔数据存储方式:In-Memory、MySql、Cassandra以及Elasticsearch。
在企业应用中一般是Sleuth和zipkin一起使用。
资料中已经提供好了zipkin的jar包,位置为:https://gitee.com/x-shuais/zipkin.git
启动zipkin服务:
zipkin服务端口号为9411,访问地址:http://localhost:9411
为了方便演示链路追踪效果,我们导入四个maven工程,位置:https://gitee.com/x-shuais/zipkin.git
分别为sleuth_parent、sleuth_client1、sleuth_client2、sleuth_client3。
maven工程说明:
sleuth_parent/pom.xml:
application.yml:
注:sleuth_client1、sleuth_client2、sleuth_client3的application.yml中的端口和应用名称配置不同,其他都相同。
分别启动sleuth_client1、sleuth_client2、sleuth_client3,访问:http://localhost:9101/trace-1
整个流程调用成功,此时访问zipkin,点击“依赖”按钮,进入如下页面:
可以看到,zipkin已经收集到调用链路的数据,并在页面上将依赖关系展示出来了。
点击查找按钮,进入查找页面:
可以看到对于刚才调用过程的数据分析。
Span:基本工作单元,发送一个远程调用就会产生一个Span,Span是一个64位ID唯一标识的,Trace是用另一个64位ID唯一标识的,Span还有其他数据信息,比如摘要、时间戳事件、Span的ID
Trace:一系列Span组成的一个树状结构。请求一个微服务系统的API接口,这个API接口需要调用多个微服务,调用每个微服务都会产生一个新的Span,所有由这个请求产生的Span组成了这个Trace
Annotation:用来定义一个请求的开始和结束 。这些注解包括以下:
前面的入门案例中zipkin展示的数据是使用默认的存储方式,即内存存储。如果zipkin服务重启则数据丢失。在实际企业应用中,这些数据是需要持久化存储的,本小节我们就将zipkin的数据存储方式改为MySQL存储。
第一步:从如下地址获取建表脚本
https://github.com/openzipkin/zipkin/blob/master/zipkin-storage/mysql-v1/src/main/resources/mysql.sql
第二步:创建数据库zipkin
第四步:执行如下命令启动zipkin
java -jar zipkin-server-2.12.2-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=127.0.0.1 --MYSQL_TCP_PORT=3306 --MYSQL_DB=zipkin --MYSQL_USER=root --MYSQL_PASS=root
3.5 通过MQ发送数据
sleuth提供了多种方式将追踪数据传输给zipkin,如下:
Sleuth 默认采用Http方式将追踪数据传输给Zipkin,也可以显示的在application.yml中进行指定:
http 传输过程中如果由于不可抗因素导致http通信中断,那么此次通信的数据将会丢失。而使用中间件的话,RabbitMQ消息队列可以积压千万级别的消息,下次重连之后可以继续消费。随着线程增多,并发量提升之后,RabbitMQ异步发送数据明显具有优势。
操作过程:
第一步:在sleuth_parent/pom.xml文件中导入mq坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
第二步:配置各个服务的application.yml文件
server:
port: 9101
spring:
application:
name: trace-1
sleuth:
sampler:
probability: 1 #这个是收集比例,1表示100% ,全部收集
zipkin:
base-url: http://localhost:9411
sender:
type: rabbit
rabbitmq:
host: 68.79.7.219
port: 5672
username: admin
password: admin@2020
virtual-host: /
第三步:执行下面命令重启zipkin
java -jar zipkin-server-2.12.2-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=127.0.0.1 --MYSQL_TCP_PORT=3306 --MYSQL_DB=zipkin --MYSQL_USER=root --MYSQL_PASS=root --RABBIT_ADDRESSES=68.79.7.219:5672 --RABBIT_USER=admin --RABBIT_PASSWORD=admin@2020 --RABBIT_VIRTUAL_HOST=/