Spring Cloud之分布式链路跟踪服务Sleuth

随着你的微服务部署节点的增多,以及对各个微服务的拆分后,对服务本身的日志和调用链路的监控就变得越来越难。这就需要一个能快速定位分布式系统下问题的需求,Spring Cloud Sleuth就是为了解决分布式链路追踪这个问题而产生的。

目前业界比较优秀的分布式链路追踪产品如Google的Dapper,Twitter的Zipkin,阿里的“鹰眼”,大众点评的CAT等。

本文主要讲述如何在Spring Cloud Sleuth中集成Zipkin,实现对微服务的日志跟踪和分布式链路的调用监控及展示。

1. Spring Cloud Sleuth介绍

Spring Cloud Sleuth implements a distributed tracing solution for Spring Cloud.

Spring Cloud Sleuth的实体概念主要来源于谷歌在2010年发表的一篇论文:《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》

  • Span: 基本工作单元,发送一个远程调用(RPC)就会产生一个新的Span,Span是一个64位ID唯一的,Trace是用另一个64位ID唯一标记的,Span还有其他数据信息比如摘要、时间戳事件、Span的ID、以及进程ID。
  • Trace: A set of spans forming a tree-like structure. For example, if you are running a distributed big-data store, a trace might be formed by a put request.
  • Annotation: 用来记录事件,cs - Client Sent,sr - Server Received,ss - Server Sent,cr - Client Received。

以Twitter的Zipkin为例,其Span和Trace在分布式系统中的概念体现如下图所示:
image

Spring Cloud Sleuth的官方文档可参考:Spring Cloud Sleuth

2. 微服务日志追踪

2.1 日志输出

对一个普通的基础SpringBoot的项目来说,如果你没有实现自定义的logback.xml,默认打印的日志格式可如下图所示:
image

若想实现Spring Cloud Sleuth的日志跟踪服务,只需要在你的Spring Cloud的项目pom文件中加上依赖:

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>

在配置文件application或bootstrap中加上配置:

1
spring.zipkin.service.name=your-log-name

此时日志格式就如下图:
image

此时log会比之前多了sleuth的部分:

1
[zhaoyh-log,888114b702f9c3aa,888114b702f9c3aa,true]

这四段内容分别是:

  • serviceName: 你指定的sleuth的service, the name of the application that logged the span.
  • traceId: the id of the latency graph that contains the span.
  • spanId: the id of a specific operation.
  • exportable: whether the log should be exported to Zipkin or not.

2.2 日志收集

假如你正在ELK框架治理你的日志,可以修改logstash的parse脚本处理日志:

1
2
3
4
5
6
filter {
# pattern matching logback pattern
grok {
match => { "message" => "%{TIMESTAMP_ISO8601:timestamp}\s+%{LOGLEVEL:severity}\s+\[%{DATA:service},%{DATA:trace},%{DATA:span},%{DATA:exportable}\]\s+%{DATA:pid}\s+---\s+\[%{DATA:thread}\]\s+%{DATA:class}\s+:\s+%{GREEDYDATA:rest}" }
}
}

直接在网页调试grok脚本的有效性,可参考Grok Debugger

3. 分布式链路追踪

本文介绍分布式链路追踪是以Spring Cloud Sleuth集成Zipkin服务为基础,为此,一共需要准备4个微服务工程,点击可直接查看代码:

3.1 启动eureka server

首先启动一个eureka server的服务,如果你不明白这是什么意思,那么我建议你从头开始再学习一遍Spring Boot和Spring Cloud的基础哈!

3.2 启动zipkin server

有三种方式启动一个Zipkin Server,第一种是自己基于Spring Cloud创建一个工程,加入依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>
</dependencies>

使用注解,启动Zipkin Server 服务:

1
2
3
4
5
6
7
8
9
10
@SpringBootApplication
@EnableDiscoveryClient
@EnableZipkinServer
public class SpringcloudZipkinServerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudZipkinServerApplication.class, args);
}
}

第二种是使用docker,首先拉取公共镜像:

1
docker pull openzipkin/zipkin

启动:

1
docker run -p 9411:9411 --name zipkin openzipkin/zipkin

第三种是通过Zipkin官方脚本下载zipkin的jar包直接运行:

1
2
curl -sSL https://zipkin.io/quickstart.sh | bash -s
java -jar zipkin.jar

查看本地的Zipkin Server的页面 http://localhost:9411/zipkin/ 如下图所示:
image

3.3 构建zuul-gateway服务

构建基于zuul的网管服务可参考之前的博文:Spring Cloud微服务框架之服务网关Zuul,再做相应的修改即可,首先pom中加入:

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>

Spring Cloud应用在检测到依赖有sleuth和zipkin后,会自动在调用过程中向HTTP请求注入追踪信息,并向Zipkin Server发送这些信息。同时配置文件中添加如下代码:

1
2
3
4
#zipkin
spring.zipkin.service.name=zuul-gateway
spring.zipkin.base-url=http://localhost:9411
spring.sleuth.sampler.percentage=1.0

spring.zipkin.service.name指定了此追踪的名称,spring.zipkin.base-url指定了Zipkin Server的地址,spring.sleuth.sampler.percentage将采样比例设置为1.0,即全部都需要,所设置的值介于0.0到1.0之间,对应不同的比例。

同时配置文件中加入需要调用的my-service服务的路由地址:

1
2
3
#zuul-serviceId
zuul.routes.client.path=/client/**
zuul.routes.client.serviceId=MY-SERVICE-TEST

启动zuul-gate服务,端口为15050,同时,对与my-service项目,也是跟zuul同样的修改方式,并加入一个返回服务的方法:

1
2
3
4
@GetMapping(value = "/api/testZuul")
public String testZuul() {
return "zuul->client: " + port;
}

启动my-service。

3.4 测试

浏览器输入:http://localhost:15050/client/api/testZuul ,此时就由zuul-gateway调用了my-service的服务。此时查看zipkin server,搜索到一条记录:
image

点击记录,可以看到这次请求在每个微服务耗费的时间:
image

点击依赖分析按钮,可以查看服务的依赖关系,在本案例中,zuul-gateway将请求转发到了my-service,它们的依赖关系如图:

image

4. Spring Cloud Sleuth进阶

在前两节,我们介绍了分布式链路跟踪服务的基本应用,这对生产级别来说还不够用,接下来,我们继续深入Sleuth,讲述使用消息队列来传输链路数据,并对链路数据的持久化做个探究。

4.1 使用消息队列RabbitMQ传递链路数据

在第三节中,Zipkin Server收集到的数据,是zuul-gateway和my-service通过http传输的。Spring Cloud Sleuth支持消息中间件来通信,我们可以直接通过RabbitMQ,来实现各个服务和Zipkin Server的通信。首先在Zipkin Server中加入依赖:

1
2
3
4
5
6
7
8
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>

配置文件中加入RabbitMQ的链接配置:

1
2
3
spring.rabbitmq.addresses=IP:5672
spring.rabbitmq.username=XX
spring.rabbitmq.password=XXXXX

替换启动类的注解:

1
2
3
4
5
6
7
8
9
10
@SpringBootApplication
@EnableDiscoveryClient
@EnableZipkinStreamServer
public class SpringcloudZipkinServerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudZipkinServerApplication.class, args);
}
}

对于其他的各个微服务来说,只需要加入依赖和RabbitMQ的链接配置即可,这样就能将链路监控数据上传方式从http修改为消息组件RabbitMQ。

4.2 链路数据持久化策略

在前述的所有例子中,Zipkin Server是将链路数据存储在内存中,一旦重启,之前的链路数据全部丢失。Zipkin支持将链路数据持久化存储在MySQL、ElasticSearch、Cassandra等。在生产环境下,可以根据需要和存储条件,合理的将数据持久化,本文由于篇幅有限,就不再详细展示持久化存储的配置过程。

5. 主要参考文档

  1. https://cloud.spring.io/spring-cloud-sleuth/1.3.x/single/spring-cloud-sleuth.html
  2. Tracing messages in Choreography with Sleuth and Zipkin
  3. Dapper, a Large-Scale Distributed Systems Tracing Infrastructure

以上内容就是关于Spring Cloud之分布式链路跟踪服务Sleuth的全部内容了,谢谢你阅读到了这里!

Author:zhaoyh