这是SpringCloud实战系列中第7篇文章,了解前面第两篇文章更有助于更好理解本文内容:
①SpringCloud 实战:引入Eureka组件,完善服务治理
②SpringCloud 实战:引入Feign组件,发起服务间调用
③SpringCloud 实战:使用 Ribbon 客户端负载均衡
④SpringCloud 实战:引入Hystrix组件,分布式系统容错
⑤SpringCloud 实战:引入Zuul组件,开启网关路由
⑥SpringCloud 实战:引入gateway组件,开启网关路由功能html
近年来,随着微服务架构的流行,不少公司都走上了微服务拆分之路。从而使系统变得愈来愈复杂,本来单体的系统被拆成不少个服务,每一个服务之间经过轻量级的 HTTP 协议进行交互。java
单体架构时,一个请求的调用链路很是清晰,通常由负载均衡器,好比 Nginx。将调用方的请求转发到后端服务,后端服务进行业务处理后返回给调用方。而当架构变成微服务架构时,可能带来一系列的问题,好比下面三个问题:spring
分布式链路跟踪原理在于如何能将请求通过的服务节点都关联起来。当一个请求从客户端到达网关后,至关因而第一个入口,这时就须要生成一个惟一的请求 ID,做为此次请求的标识。从网关到达服务 A 后,确定是须要将请求 ID 传递到服务 A 中的,这样才能将网关到服务 A 的请求关联起来,依次类推,后面会通过多层服务,都须要将信息一层层传递。固然在每一层都须要将数据进行上报、统一存储、展现等操做。后端
从咱们对这个需求的理解来看,链路跟踪并非很复杂,而复杂的点在于如何实现这一套跟踪框架,就拿请求信息传递这件事来讲,服务之间交互,有的用的是 Feign 调用接口,有的用的是 RestTemplate 调用接口,要想将信息传递到下游服务,那么必须得扩展这些调用的框架才能够。bash
Span服务器
基本工做单元,例如,发送 RPC 请求是一个新的 Span,发送 HTTP 请求是一个新的 Span,内部方法调用也是一个新的 Span。网络
Trace架构
一次分布式调用的链路信息,每次调用链路信息都会在请求入口处生成一个 TraceId
。负载均衡
Annotation框架
用于记录事件的信息。在 Annotation 中会有 CS、SR、SS、CR 这些信息,前面的C表示客户端,S表示服务器端; 后面的S表示sent,也就是发起请求时的动做,R表示Received,也就是接受到请求时的动做;下面分别介绍下这些信息的做用。
Client Sent
,客户端发起一个请求,这个 Annotation 表示 Span 的开始。Client Received
,表示 Span 的结束,客户端已成功从服务器端收到响应,用 CR 的时间戳减去 CS 的时间戳就能够知道客户端从服务器接收响应所需的所有时间。Server Sent
,在请求处理完成时将响应发送回客户端,用 SS 的间戳减去 SR 的时间戳会显示服务器端处理请求所需的时间。Server Received
,服务器端得到请求并开始处理它,用 SR 的时间戳减去 CS 的时间戳会显示网络延迟时间。Zipkin
是 Twitter
的一个开源项目,是一个致力于收集全部服务监控数据的分布式跟踪系统,它提供了收集数据和查询数据两大接口服务。有了 Zipkin
咱们就能够很直观地查看调用链,而且可能很方便看出服务之间的调用关系,以及调用耗费的时间。
Zipkin还提供了可插拔数据存储方式:In-Memory、MySql、Cassandra以及Elasticsearch。测试方即可直接采用In-Memory方式进行存储,生产推荐使用Elasticsearch。
若是使用了 Java 8 或者更高的版本,能够获取最新的可执行 jar 包来进行启动。
下载jar包:
curl -sSL https://zipkin.io/quickstart.sh | bash -s
若是下载太慢,能够直接访问Maven地址进行下载最新的jar。
其余方式安装,能够查看官网的quickstart。
启动服务
java -jar zipkin.jar
访问Zipkin
成功启动服务后,访问http://127.0.0.1:9411/zipkin/便可。
Spring Cloud Sleuth
是一种分布式的服务链路跟踪解决方案,经过使用 Spring Cloud Sleuth 可让咱们快速定位某个服务的问题,以及厘清服务间的依赖关系。
Sleuth
能够添加链路信息到日志中,这样的好处是能够统一将日志进行收集展现,而且能够根据链路的信息将日志进行串联。
Sleuth 中的链路数据可直接上报给 Zipkin
,在 Zipkin
中就能够直接查看调用关系和每一个服务的耗时状况.
Sleuth 中内置了不少框架的埋点,好比:Zuul、Feign、Hystrix、RestTemplate
等。正由于有了这些框架的埋点,链路信息才能一直往下传递。
在咱们的微服务项目中添加Zipkin依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency>
配置Zipkin地址
spring.zipkin.base-url=http://127.0.0.1:9411/
配置采样比例
实际使用中可能调用了 10 次接口,可是 Zipkin 中只有一条数据,这是由于收集信息是有必定比例的,Zipkin 中的数据条数与调用接口次数默认比例是 10:1,经过下面的配置来改变这个比例值:
spring.sleuth.sampler.probability=1.0
验证
启动咱们的微服务,访问 http://localhost:9000/eureka-client/sayHello 接口,接口由网关路由到eureka-client 服务,eureka-client 服务再调用eureka-provider服务,接口返回eureka-provider服务的端口等信息。
而后访问 http://127.0.0.1:9411/zipkin ,点击查询,便可查看到相关访问记录
点击菜单上面的依赖,能够查看项目的依赖关系
数据的发送若是采用 HTTP 对性能仍是有影响的。若是Zipkin 的服务端在重启或者挂掉时,那么将丢失部分采集数据。为了解决这些问题,咱们能够集成 RabbitMQ 或者Kafka 来发送采集数据,利用消息队列来提升发送性能,保证数据不丢失;
若是要使用RabbitMQ或Kafka而不是HTTP,须要引入spring-rabbit
or spring-kafka
相关依赖。
<dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit</artifactId> </dependency>
而后在配置文件修改相关配置:
# WEB、KAFKA、RABBIT、ACTIVEMQ spring.zipkin.sender.type=kafka
删除以前配置的 spring.zipkin.base-url
配置kafka、rabbit
每一个跟踪系统都须要具备Reporter <Span>
和Sender
,若是要覆盖提供的bean,则须要给它们指定一个特定的名称 ZipkinAutoConfiguration.REPORTER_BEAN_NAME
and ZipkinAutoConfiguration.SENDER_BEAN_NAME
。
下面是示例:
@Configuration protected static class MyConfig { @Bean(ZipkinAutoConfiguration.REPORTER_BEAN_NAME) Reporter<zipkin2.Span> myReporter() { return AsyncReporter.create(mySender()); } @Bean(ZipkinAutoConfiguration.SENDER_BEAN_NAME) MySender mySender() { return new MySender(); } static class MySender extends Sender { private boolean spanSent = false; boolean isSpanSent() { return this.spanSent; } @Override public Encoding encoding() { return Encoding.JSON; } @Override public int messageMaxBytes() { return Integer.MAX_VALUE; } @Override public int messageSizeInBytes(List<byte[]> encodedSpans) { return encoding().listSizeInBytes(encodedSpans); } @Override public Call<Void> sendSpans(List<byte[]> encodedSpans) { this.spanSent = true; return Call.create(null); } } }