⑦SpringCloud 实战:引入Sleuth组件,完善服务链路跟踪
这是SpringCloud实战系列中第7篇文章,了解前面第两篇文章更有助于更好理解本文内容:
①SpringCloud 实战:引入Eureka组件,完善服务治理
②SpringCloud 实战:引入Feign组件,发起服务间调用
③SpringCloud 实战:使用 Ribbon 客户端负载均衡
④SpringCloud 实战:引入Hystrix组件,分布式系统容错
⑤SpringCloud 实战:引入Zuul组件,开启网关路由
⑥SpringCloud 实战:引入gateway组件,开启网关路由功能
背景
近年来,随着微服务架构的流行,很多公司都走上了微服务拆分之路。从而使系统变得越来越复杂,原本单体的系统被拆成很多个服务,每个服务之间通过轻量级的 HTTP 协议进行交互。
单体架构时,一个请求的调用链路非常清晰,一般由负载均衡器,比如 Nginx。将调用方的请求转发到后端服务,后端服务进行业务处理后返回给调用方。而当架构变成微服务架构时,可能带来一系列的问题,比如下面三个问题:
- 接口响应慢,怎么排查?
- 服务间的依赖关系如何查看?
- 请求贯穿多个微服务,如何将每个请求的日志串起来?
分布式链路跟踪
分布式链路跟踪原理在于如何能将请求经过的服务节点都关联起来。当一个请求从客户端到达网关后,相当于是第一个入口,这时就需要生成一个唯一的请求 ID,作为这次请求的标识。从网关到达服务 A 后,肯定是需要将请求 ID 传递到服务 A 中的,这样才能将网关到服务 A 的请求关联起来,依次类推,后面会经过多层服务,都需要将信息一层层传递。当然在每一层都需要将数据进行上报、统一存储、展示等操作。
从我们对这个需求的理解来看,链路跟踪并不是很复杂,而复杂的点在于如何实现这一套跟踪框架,就拿请求信息传递这件事来说,服务之间交互,有的用的是 Feign 调用接口,有的用的是 RestTemplate 调用接口,要想将信息传递到下游服务,那么必须得扩展这些调用的框架才可以。

核心概念
Span
基本工作单元,例如,发送 RPC 请求是一个新的 Span,发送 HTTP 请求是一个新的 Span,内部方法调用也是一个新的 Span。
Trace
一次分布式调用的链路信息,每次调用链路信息都会在请求入口处生成一个
TraceId。Annotation
用于记录事件的信息。在 Annotation 中会有 CS、SR、SS、CR 这些信息,前面的C表示客户端,S表示服务器端; 后面的S表示sent,也就是发起请求时的动作,R表示Received,也就是接受到请求时的动作;下面分别介绍下这些信息的作用。
- CS
也就是Client Sent,客户端发起一个请求,这个 Annotation 表示 Span 的开始。 - CR
也就是Client Received,表示 Span 的结束,客户端已成功从服务器端收到响应,用 CR 的时间戳减去 CS 的时间戳就可以知道客户端从服务器接收响应所需的全部时间。 - SS
也就是Server Sent,在请求处理完成时将响应发送回客户端,用 SS 的间戳减去 SR 的时间戳会显示服务器端处理请求所需的时间。 - SR
也就是Server Received,服务器端获得请求并开始处理它,用 SR 的时间戳减去 CS 的时间戳会显示网络延迟时间。
- CS
请求追踪过程分解

- 首先当一个请求访问 SERVICE1 时,这时是没有 Trace 和 Span 的,然后会生成 Trace 和 Span,如图所示生成的 Trace ID 是 X,Span ID 是 A。
- 接着 SERVICE1 请求 SERVICE2,这是一次远程请求,会生成一个新的 Span,Span ID 为 B,Trace ID 不变还是 X。Span B 处于 CS 状态。
- 当请求到达 SERVICE2 后,Trade ID 和 Span ID 就被传递过来了,这时,SERVICE2 有内部操作,又生成了一个新的 Span,Span ID 为 C,Trace ID 不变还是 X。
- SERVICE2 处理完后向 SERVICE3 发起请求,同时产生新的 Span,Span ID 为 D,Span D 处于 CS 状态,SERVICE3 接收到请求后,Span D 处于 SR 状态,同时 SERVICE3 内部操作也会产生新的 Span,Span ID 为 E。
- 当 SERVICE3 处理完后,需要将结果响应给调用方,这时 Span D 就处于 SS 的状态,当 SERVICE2 收到响应后,Span ID 为 D 的 Span 就是 CR 状态,表示 Span 已经结束了。
Zipkin 介绍
Zipkin 是 Twitter 的一个开源项目,是一个致力于收集所有服务监控数据的分布式跟踪系统,它提供了收集数据和查询数据两大接口服务。有了 Zipkin 我们就可以很直观地查看调用链,并且可能很方便看出服务之间的调用关系,以及调用耗费的时间。
Zipkin还提供了可插拔数据存储方式:In-Memory、MySql、Cassandra以及Elasticsearch。测试方便可直接采用In-Memory方式进行存储,生产推荐使用Elasticsearch。
安装 Zipkin
如果使用了 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/即可。

Sleuth 介绍
Spring Cloud Sleuth 是一种分布式的服务链路跟踪解决方案,通过使用 Spring Cloud Sleuth 可以让我们快速定位某个服务的问题,以及厘清服务间的依赖关系。
Sleuth 可以添加链路信息到日志中,这样的好处是可以统一将日志进行收集展示,并且可以根据链路的信息将日志进行串联。
Sleuth 中的链路数据可直接上报给 Zipkin,在 Zipkin 中就可以直接查看调用关系和每个服务的耗时情况.
Sleuth 中内置了很多框架的埋点,比如:Zuul、Feign、Hystrix、RestTemplate 等。正因为有了这些框架的埋点,链路信息才能一直往下传递。
通过 Http 结合Zipkin
在我们的微服务项目中添加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 ,点击查询,即可查看到相关访问记录

点击菜单上面的依赖,可以查看项目的依赖关系

使用 RabbitMQ or Kafka 代替 HTTP 发送调用链数据
数据的发送如果采用 HTTP 对性能还是有影响的。如果Zipkin 的服务端在重启或者挂掉时,那么将丢失部分采集数据。为了解决这些问题,我们可以集成 RabbitMQ 或者Kafka 来发送采集数据,利用消息队列来提高发送性能,保证数据不丢失;
如果要使用RabbitMQ或Kafka而不是HTTP,需要引入
spring-rabbitorspring-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
自定义 Zipkin 配置
每个跟踪系统都需要具有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);
}
}
}
⑦SpringCloud 实战:引入Sleuth组件,完善服务链路跟踪的更多相关文章
- Zipkin和微服务链路跟踪
https://cloud.tencent.com/developer/article/1082821 Zipkin和微服务链路跟踪 本期分享的内容是有关zipkin和分布式跟踪的内容. 首先,我们还 ...
- 服务链路跟踪 && 服务监控
服务链路跟踪 背景 微服务以微出名,在实际的开发过程中,涉及到成百上千个服务,网络请求引起服务之间的调用极其复杂. 当请求不可用或者变慢时,需要及时排查出故障服务点成为了微服务维护的一大难关. 服务链 ...
- SpringCloud学习之Sleuth服务链路跟踪(十二)
一.为什么需要Spring Cloud Sleuth 微服务架构是一个分布式架构,它按业务划分服务单元,一个分布式系统往往有很多个服务单元.由于服务单元数量众多,业务的复杂性,如果出现了错误和异常,很 ...
- Spring Cloud Sleuth+ZipKin+ELK服务链路追踪(七)
序言 sleuth是spring cloud的分布式跟踪工具,主要记录链路调用数据,本身只支持内存存储,在业务量大的场景下,为拉提升系统性能也可通过http传输数据,也可换做rabbit或者kafka ...
- SpringCloud学习成长之 九 服务链路跟踪
这篇文章主要讲述服务追踪组件zipkin,Spring Cloud Sleuth集成了zipkin组件. 一.简介 Spring Cloud Sleuth 主要功能就是在分布式系统中提供追踪解决方案, ...
- SpringCloud入门(十一):Sleuth 与 Zipkin分布式链路跟踪
现今业界分布式服务跟踪的理论基础主要来自于 Google 的一篇论文<Dapper, a Large-Scale Distributed Systems Tracing Infrastructu ...
- SpringCloud实战-Hystrix请求熔断与服务降级
我们知道大量请求会阻塞在Tomcat服务器上,影响其它整个服务.在复杂的分布式架构的应用程序有很多的依赖,都会不可避免地在某些时候失败.高并发的依赖失败时如果没有隔离措施,当前应用服务就有被拖垮的风险 ...
- SpringCloud实战3-Hystrix请求熔断与服务降级
我们知道大量请求会阻塞在Tomcat服务器上,影响其它整个服务.在复杂的分布式架构的应用程序有很多的依赖,都会不可避免地在某些时候失败.高并发的依赖失败时如果没有隔离措施,当前应用服务就有被拖垮的风险 ...
- Zipkin — 微服务链路跟踪.
一.Zipkin 介绍 Zipkin 是什么? Zipkin的官方介绍:https://zipkin.apache.org/ Zipkin是一款开源的分布式实时数据追踪系统(Distributed ...
随机推荐
- 数据丢失如何恢复?EasyRecovery帮你快速实现
在日常使用电脑时,我们经常会遇到误删文件的情况,若文件还未被彻底删除,我们还可以通过电脑中的回收站将其恢复,但若是回收站都被清空的话,想要恢复文件就变得比较困难了,而EasyRecovery可以很好的 ...
- jQuery 第三章 CSS操作
.css() .attr() .prop() .css() 参数填法:如下所示 ↓ 可填px 可不填,注意点:background-color 这类属性,需要填成 小驼峰式 background ...
- vue springboot利用easypoi实现简单导出
vue springboot利用easypoi实现简单导出 前言 一.easypoi是什么? 二.使用步骤 1.传送门 2.前端vue 3.后端springboot 3.1编写实体类(我这里是dto, ...
- 【P2634】聪聪可可——点分治
(题面来自Luogu) 题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)--遇到这种问题,一般情况下石头 ...
- 多态,向上转型,向下转型,final关键字
多态 概述 多态封装性,继承性之后,面向对象的第三大特性. 定义 多态:是指同一种行为,具有多个不同的表现形式. 生活中,比如跑的动作,猫,狗,大象跑起来的动作都是不一样的,再比如飞的动作 ...
- 盘点腾讯Linux、 C++后台开发面试题,做好充足准备,不怕被Pass
一.C/C++ const 多态 什么类不能被继承 二.网络 网络的字节序 网络知识 TCP三次握手 各种细节 timewait状态 TCP与UDP的区别 概念 适用范围 TCP四次挥 ...
- synchronized底层揭秘
前言 上篇文章我们从硬件级别探索,对可见性和有序性的认识上升了一个高度,却迟迟没有介绍原子性的解决方案. 今天我们就来聊一聊原子性的解决方案,锁. 引入锁机制,除了可以保证原子性,同时也可以保证可见性 ...
- day3(axios封装)
1. 始vue化项目 https://www.cnblogs.com/xiaonq/p/11027880.html vue init webpack deaxios # 使用脚手架创建项目 d ...
- 第15.38节 PyQt(Python+Qt)入门学习:containers容器类部件QDockWidget停靠窗功能详解
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.概述 QDockWidget类提供了一个可以停靠在QMainWin ...
- 第14.18节 爬虫实战4: request+BeautifulSoup+os实现利用公众服务Wi-Fi作为公网IP动态地址池
写在前面:本文相关方法为作者独创,仅供参考学习爬虫技术使用,请勿用作它途,禁止转载! 一. 引言 在爬虫爬取网页时,有时候希望不同的时候能以不同公网地址去爬取相关的内容,去网上购买地址资源池是大部分人 ...