Spring Cloud Sleuth整合Zipkin
本节我们用Spring Cloud Sleuth整合Zipkin,将微服务产生的日志交给Zipkin去分析,Zipkin是一个分布式追踪系统,主要用于收集、管理微服务产生的数据。Zipkin的设计是基于Google Dapper实现的。在实际应用时,我们需要让各个微服务向Zipkin服务器报告过程数据。
Spring Cloud Sleuth整合Zipkin的实现过程并不复杂,我们只需要加入依赖,以及做简单配置,就可以实现Zipkin“写入”数据。在Zipkin得到“写入”的数据后,提供了数据查询、分析的功能,这些图形化的功能,可以让我们对微服务的调用过程、处理时间、依赖关系等数据一目了然。
下面我们通过一个案例来详细讲解Spring Cloud Sleuth整合Zipkin。
1、 搭建Eureka Server
这里使用2.2.1小节搭建的Spring Boot项目eureka-server作为Eureka Server。
2、 创建Zipkin服务端
用于进行数据的采集存储、数据的分析和数据的展示等
(1)使用Spring Initializr方式创建一个名称为zipkin-server的Spring Boot项目,这里将Group命名为com.itheima,将Artifact命名为zipkin-server,添加Eureka Server、Test、Zipkin和Zipkin图形化界面的依赖,如下所示。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server
</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
<version>2.11.8</version>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
<version>2.11.8</version>
</dependency>
(2)在全局配置文件application.yml进行相关配置,包括应用名称、端口号、服务注册地址以及自动收集Web请求的相关配置等。配置后的application.yml文件,如例1所示。
例1 zipkin-server\src\main\resources\application.yml
1 server:
2 port: 9411
3 spring:
4 application:
5 name: zipkin
6 eureka:
7 client:
8 service-url:
9 defaultZone: http://localhost:7000/eureka/
10 management:
11 metrics:
12 web:
13 server:
14 auto-time-requests: false #关闭自动收集web请求
(3)在zipkin-server项目启动类ZipkinServerApplication上添加注解
@EnableZipkinServer将服务标注为Zipkin Server,如例2所示。
例2 zipkin-server\src\main\java\com\itheima\zipkinserver\ZipkinServerApplication.java
1 import org.springframework.boot.SpringApplication;
2 import org.springframework.boot.autoconfigure.SpringBootApplication;
3 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
4 import zipkin2.server.internal.EnableZipkinServer;
5 @SpringBootApplication
6 @EnableZipkinServer
7 @EnableDiscoveryClient
8 public class ZipkinServerApplication {
9 public static void main(String[] args) {
10 SpringApplication.run(ZipkinServerApplication.class, args);
11 }
12 }
(4)启动测试。依次启动项目eureka-server、zipkin-server,使用浏览器访问http://localhost:9411
,如果出现如图1所示的界面,表示Zipkin服务端搭建成功。
图1 Zipkin访问效果图
3、 创建网关服务
(1)使用Spring Initializr方式创建一个名称为gateway-service的Spring Boot项目作为网关服务,这里将Group命名为com.itheima,将Artifact命名为gateway-service,添加Eureka Server、Test、Zuul、Zipkin的依赖,如下所示。
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server
</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
(2)在全局配置文件application.yml进行相关配置,包括服务名称、端口号、服务注册地址以及Zuul的相关配置,具体如例3所示。
例3 gateway-service\src\main\resources\application.yml
1 server:
2 port: 9410
3 spring:
4 application:
5 name: gateway-service
6 zipkin:
7 base-url: http://localhost:9411/
8 sleuth:
9 sampler:
10 probability: 1.0
11 rabbitmq:
12 host: localhost
13 port: 5672
14 username: guest
15 password: guest
16 eureka:
17 client:
18 service-url:
19 defaultZone: http://localhost:7000/eureka/
20 management:
21 metrics:
22 web:
23 server:
24 auto-time-requests: false
25 zuul: #配置Zuul设置
26 routes:
27 eureka-provider:
28 path: /eureka-provider/** #Zuul路由的前缀
29 host: #超时设置
30 socket-timeout-millis: 60000
31 connect-timeout-millis: 10000
(3)在启动类GatewayServiceApplication添加注解@EnableEurekaClient和@EnableZuulProxy开启Eureka Client功能和Zuul代理功能,如例4所示。
例4 gateway-service\src\main\java\com\itheima\gatewayservice\GatewayServicApplication.java
1 import org.springframework.boot.SpringApplication;
2 import org.springframework.boot.autoconfigure.SpringBootApplication;
3 import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
4 import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
5 @SpringBootApplication
6 @EnableZuulProxy
7 @EnableEurekaClient
8 public class GatewayServiceApplication {
9 public static void main(String[] args) {
10 SpringApplication.run(GatewayServiceApplication.class, args);
11 }
12 }
4、 创建生产者eureka-provider
(1)使用Spring Initializr方式创建一个名称为eureka-provider的Spring Boot项目Zipkin客户端的生产者,这里将Group命名为com.itheima,将Artifact命名为eureka-provider,添加Zipkin依赖,如下所示。
<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>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
</dependencies>
(2)在全局配置文件application.yml中进行相关配置,包括端口号、服务名称、服务注册地址以及Zipkin和Sleuth的相关配置等,如例5所示。
例5 eureka-provider\src\main\resources\application.yml
1 server:
2 port: 7010
3 spring:
4 application:
5 name: eureka-provider
6 eureka:
7 client:
8 service-url:
9 defaultZone: http://localhost:7000/eureka
10 instance:
11 hostname: localhost
12 zipkin:
13 base-url: http://localhost:9411/zipkin/
14 sleuth:
15 sampler:
16 probability: 1.0
(3)修改eureka-provider的启动类,在启动类上添加注解@EnableEurekaClient,开启服务的Eureka Client功能。添加RestTemplate的Bean实例方法restTemplate(),并在restTemplate()方法上添加@LoadBalanced注解,开启负载均衡的功能。再添加一个service1()方法,在service1()方法中通过restTemplate().getForObject("http://eureka-consumer/service2
",String.class)调用eureka-consumer的service2()方法,并返回service2()方法的返回值。。具体代码如例6所示。
例6 eureka-provider\src\main\java\com\itheima\eurekaprovider\EurekaProviderApplication.java
1 import org.springframework.boot.SpringApplication;
2 import org.springframework.boot.autoconfigure.SpringBootApplication;
3 import org.springframework.cloud.client.loadbalancer.LoadBalanced;
4 import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
5 import org.springframework.context.annotation.Bean;
6 import org.springframework.web.bind.annotation.RequestMapping;
7 import org.springframework.web.bind.annotation.RequestMethod;
8 import org.springframework.web.bind.annotation.RestController;
9 import org.springframework.web.client.RestTemplate;
10 @SpringBootApplication
11 @EnableEurekaClient
12 @RestController
13 public class EurekaProviderApplication {
14 public static void main(String[] args) {
15 SpringApplication.run(Service1Application.class,args);
16 }
17 @Bean
18 @LoadBalanced
19 RestTemplate restTemplate() {
20 return new RestTemplate();
21 }
22 @RequestMapping(value = "service1", method = RequestMethod.GET)
23 public String service1() {
24 return restTemplate().getForObject("http://eureka-consumer
25 /service2", String.class);
26 }
27 }
6、 创建消费者eureka-consumer
(1)创建一个消费者项目eureka-consumer,搭建步骤与eureka-provider项目一致,不同的是,这里我们将eureka-consumer的端口号设为7011,服务名称name为eureka-consumer。
(2)在eureka-consumer的启动类EurekaConsumerApplication中添加注解@EnableEurekaClient,开启Eureka Client功能,并添加service2()方法,service2()方法的返回值为eureka-provider的请求结果。具体代码如例7所示。
例7 eureka-consumer\src\main\java\com\itheima\EurekaConsumerApplication.java
1 @SpringBootApplication
2 @EnableEurekaClient
3 @RestController
4 public class EurekaConsumerApplication {
5 public static void main(String[] args) {
6 SpringApplication.run(Service2Application.class,args);
7 }
8 @RequestMapping(value = "service2", method = RequestMethod.GET)
9 public String service2() {
10 return "Hi,I'm Service2!";
11 }
12 }
7、 启动测试
(1)依次启动eureka-server、zipkin-server、eureka-provider,eureka-consumer、 gateway-service。使用浏览器访问http://localhost:7000/
,确保微服务已经成功注册到了服务注册中心,如图2所示。
图2 注册中心图
(2)通过网关访问生产者eureka-provider。使用浏览器访问http://localhost:9410/eureka-provider/service1
,访问效果如图3所示。
图3 通过网关访问生产者eureka-provider的效果图
从图3中可以看到页面显示“Hi,I'm Service2!”,说明通过网关访问生产者eureka-provider成功,此时我们查看网关服务gateway-service的控制台打印日志,发现控制台打印了以下日志信息。
2019-10-31 09:43:24.022 INFO [zipkin-zull,39decf163ebc75cc,
39decf163ebc75cc,true]
上述打印消息中共包含4个参数,具体介绍如下:
● zipkin-zull:服务名称。
● 39decf163ebc75cc:tranceId,每次请求都会有唯一的tranceId。
● 39decf163ebc75cc:spanId,每个工作单元发送一次请求就会产生一个spanId, 每
个请求会产生一个tranceId和多个spanId,根据tranceId和spanId就能分析出
一个完整的请求都经历了哪些服务单元。
● True:标记是否需要将该请求链路进行抽样收集发送到Zipkin等进行整理。
(3)访问Zipkin服务端。使用浏览器访问http://localhost:9411/
,页面会显示Zipkin服务端的UI界面,可以看到上述请求所调用的服务,如图4所示。
图4 Zipkin服务端的UI界面
在图4中,选择gateway-service,单击 “Find Trances”按钮,查看gateway-service、eureka-provider、eureka-consumer服务的调用记录,如图5所示。
图5 服务调用记录图
在图5中所示的服务调用记录中,共记录了三个服务节点,分别是gateway-service、eureka-provider、eureka-consumer。双击图5中的链路追踪信息可以查看具体的调用顺序,并且还能看到服务调用的接口以及服务调用服务处理的时间长度,如图6所示。
图6 服务调用顺序以及节点处理时间记录图
双击图6某一服务节点,可以看到该节点更详细的节点信息,这里我们查看gateway-service服务节点的详细信息,包括服务名称、请求服务节点所耗时长、HTTP请求方式、HTTP请求路径以及客户端地址等信息。如图7所示。
图7 服务调用详细信息记录图
单击图7导航栏中的依赖分析Dependencies选项,可以查看本次请求服务之间的依赖调用关系,如图8所示。
图8 服务依赖调用关系
从图8我们可以看到,客户端先通过网关服务gateway-service调用了生产者eureka-provider,然后eureka-provider调用了消费者eureka-consumer。说明Spring Cloud Sleuth整合Zipkin实现链路追踪成功。