概述
在微服务的架构下,系统由大量服务组成,每个服务可能是由不同的团队开发,开发使用不 同的语言,部署在几千台服务器上,并且横跨多个不同的数据中心,一次请求绝大多数情况 会涉及多个服务。因此,就需要一些能够帮助理解系统行为、分析系统性能问题的工具, 以便在系统发生故障的时候,快速定位和解决问题。这些工具就是APM(Application Performance Management)
Spring Cloud Sleuth 能够跟踪你的请求和消息,以便你可以将该通信与相应的日志条目相关联。 你还可以将跟踪信息导出到外部系统以可视化延迟
术语
Spring Cloud Sleuth 借用了 Dapper 的术语
Span:工作的基本单位。例如,发送 RPC 是一个新的Span,就像向 RPC 发送响应一样。Span 还有其他数据,例如描述、时间戳事件、键值注释(标签)、导致它们的 span 的 ID 和进程 ID(通常是 IP 地址)。Span 可以启动和停止,并且它们会跟踪它们的时间信息。一旦你创建了一个Span,你必须在未来的某个时候停止它。
Trace:形成树状结构的一组Span。例如,如果您运行分布式大数据存储,则PUT请求可能会形成跟踪。
Annotation/Event:用于及时记录事件的存在。从概念上讲,在典型的 RPC 场景中,我们标记这些事件以突出显示发生了何种类型的操作(这并不意味着在物理上将此类事件设置在Span上)。
- cs:Client Sent。客户提出了请求。此注释指示Span的开始。
- sr : Server Received: 服务器端收到请求并开始处理。cs从此时间戳中减去时间戳可显示网络延迟。
- ss:Server Sent。在请求处理完成时进行注释(当响应被发送回客户端时)。sr从这个时间戳中减去时间戳就显示了服务器端处理请求所需的时间。
- cr : Client Received。表示Span的结束。客户端已成功收到服务器端的响应。cs从此时间戳中减去时间戳可显示客户端从服务器接收响应所需的全部时间。
下图显示了Span和Trace在系统中的流转,图片来着springcloud官网
每个note色块代表着一个span,(有七个span - 从A到G),思考一下下面的note
Trace Id = X
Span Id = D
Client Sent
此note表明当前span将Trace Id设置为X并将span Id设置为D。此外,从 RPC 的角度来看,Client Sent事件发生了。
再思考一下下面note,
Trace Id = X
Span Id = A
(no custom span)
Trace Id = X
Span Id = C
(custom span)
您可以继续使用创建的span(带有no custom span指示的示例),也可以手动创建子span(带有custom span指示的示例)。
下图显示了span的父子关系的流转:
翻译自官网:https://docs.spring.io/spring-cloud-sleuth/docs/current/reference/html/getting-started.html#getting-started-terminology
Sleuth 通过 Trace 定义一次业务调用链,根据它的信息,我们能知道有多少个系统参与了该业务处理。而系统间的调用顺序和时间戳信息,则是通过 Span 来记录的。 Trace 和 Span 的信息经过整合,就能知道该业务的完整调用链。
入门示例
zipkin
Zipkin 是 Twitter 的一个开源项目,它基于 Google Dapper 实现。我们可以使用它来收集各个服务器上请求链路的跟踪数据,并通过它提供的 REST API 接口来辅助查询跟踪数据以实现对分布式系统的监控程序,从而及时发现系统中出现的延迟升高问题并找出系统性能瓶颈的根源。除了面向开发的 API 接口之外,它还提供了方便的 UI 组件来帮助我们直观地搜索跟踪信息和分析请求链路明细,比如可以查询某段时间内各用户请求的处理时间等。下图展示了 Zipkin 的基础架构,它主要由4个核心组件构成。
Zipkin Collector
收集器组件,它主要处理从外部系统发送过来的跟踪信息,将这些信息转换为 Zipkin 内部处理的 Span 格式,以支持后续的存储、分析、展示等功能。
Storage
存储组件,它主要处理收集器接收到的跟踪信息,默认会将这些信息存储在内存中。我们也可以修改此存储策略,通过使用其他存储组件将跟踪信息存储到数据库中。
Zipkin Query Service
Zipkin 查询服务组件,它主要用来提供外部访问接口。比如给客户端展示跟踪信息,或是外接系统访问以实现监控等。它的主要使用者是Web UI组件。
Web UI
UI 组件,基于 API 组件实现的上层应用。通过 UI 组件,用户可以方便而又直观地查询和分析跟踪信息。注意:UI 中没有内置身份验证!
与zipkin整合
1、创建一个cloud-sleuth 项目,搭建一个zipkin server,依赖如下
<properties>
<java.version>1.8</java.version>
<zipkin.version>2.10.0</zipkin.version>
</properties>
<dependencies>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
<version>${zipkin.version}</version>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
<version>${zipkin.version}</version>
</dependency>
2、修改配置文件
server.port=8601
spring.application.name=sleuth-zipkin-server
management.metrics.web.server.auto-time-requests=false
spring.main.allow-bean-definition-overriding=true
3、启动类加上@EnableZipkinServer注解
@EnableZipkinServer
@SpringBootApplication
public class CloudSleuthApplication {
public static void main(String[] args) {
SpringApplication.run(CloudSleuthApplication.class, args);
}
}
4、访问http://localhost:8601/,出现下面界面zipkin链路监控界面搭建就完成了
zipkin 客户端配置
zipkin server配置好之后,只有zipkin server是没啥作用的,自然是要搭配客户端使用。
1、客户端添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
2、客户端添加配置
# zipkin 服务
spring.zipkin.base-url=http://localhost:8601
# 提交类型
spring.zipkin.sender.type=web
#定义抽样比率
spring.sleuth.sampler.probability=1.0
启动的客户端:
- eureka-consumer
- eureka-provider
- user-provider
- zuul-gateway
当然eureka-server注册中心和CloudSleuthApplication也是必须要启动的
eureka-consumer通过zuul-gateway网关调用user-provider和eureka-provider,
访问
http://localhost:7001/consumer/feign/getUserName/ggg 调用user-provider
http://localhost:7001/consumer/feign/getName/hhh 调用eureka-provider
之后进入zipkin界面点击依赖分析就可以看到调用链。这样SpringCloud Sleuth基本操作就完成了。
数据持久化
上面使用的客户端所有的调用链信息都是保存在内存中的,spring.zipkin.sender.type=web 是表示http收集,每次重启zipkin server数据就丢失了并且大量的数据保存在内存中也会造成内存瓶颈,所以可以把信息保存在存储组件中,比如mysql。zipkin默认提供了对mysql的支持。,如果请并发量特别大,对于 mysql 来说可能会承受不了这么大的并发, 为了解决这个问题,可以使用消息队列缓冲处理,最后才从 消息队列中把数据存到 mysql 中。
上一篇springcloud 项目一步一步搭建(8)springcloud Stream
用到了rabbitmq,这次也使用rabbitmq作为消息中间件。
1、创建数据库zipkin
数据库表在https://github.com/openzipkin/zipkin/blob/master/zipkin-storage/mysql-v1/src/main/resources/mysql.sql
或者到jar包下面找
2、添加依赖
2.1 zipkin server端全部依赖如下
<properties>
<java.version>1.8</java.version>
<zipkin.version>2.10.0</zipkin.version>
</properties>
<dependencies>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
<version>${zipkin.version}</version>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
<version>${zipkin.version}</version>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-collector-rabbitmq</artifactId>
<version>${zipkin.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.zipkin.java/zipkin-autoconfigure-storage-mysql -->
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-storage-mysql</artifactId>
<version>${zipkin.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
</dependencies>
2.2 客户端添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
3、修改配置
3.1 zipkin server 添加配置
zipkin server 端配置可参考https://github.com/openzipkin/zipkin/blob/master/zipkin-server/src/main/resources/zipkin-server-shared.yml
zipkin.collector.sample-rate=1.0
zipkin.collector.http.enabled=false
# rabbitmq 配置
zipkin.collector.rabbitmq.addresses=localhost:5672
zipkin.collector.rabbitmq.password=guest
zipkin.collector.rabbitmq.queue=zipkin
zipkin.collector.rabbitmq.username=guest
zipkin.collector.rabbitmq.virtual-host=/
# mysql 配置
zipkin.storage.type=mysql
zipkin.storage.mysql.host=localhost
zipkin.storage.mysql.port=3306
zipkin.storage.mysql.username=root
zipkin.storage.mysql.password=1234
zipkin.storage.mysql.db=zipkin
3.2 客户端修改配置
spring.zipkin.sender.type从 web 修改为rabbit
# 提交类型
spring.zipkin.sender.type=rabbit
4、测试
再次访问
http://localhost:7001/consumer/feign/getUserName/ggg 调用user-provider
http://localhost:7001/consumer/feign/getName/hhh 调用eureka-provider
查看数据库,数据库有数据则成功
至此,SpringCloud Sleuth zipkin 链路追踪入门就完成了。
GitHub地址:
https://github.com/ArronSun/micro-services-practice.git
参考书籍:
《springcloud微服务实战》
《重新定义springcloud 实战》
能力一般,水平有限,如有错误,请多指出。