在微服务中,通常根据业务模块分服务,项目中前端发起一个请求,后端可能跨几个服务调用才能完成这个请求(如下图)。如果系统越来越庞大,服务之间的调用与被调用关系就会变得很复杂,假如一个请求中需要跨几个服务调用,其中一个服务由于网络延迟等原因挂掉了,那么这时候我们需要分析具体哪一个服务出问题了就会显得很困难。Spring Cloud Sleuth服务链路跟踪功能就可以帮助我们快速的发现错误根源以及监控分析每条请求链路上的性能等等。
一、 Spring Cloud Sleuth 简介
微服务跟踪(sleuth)其实是一个工具,它在整个分布式系统中能跟踪一个用户请求的过程(包括数据采集,数据传输,数据存储,数据分析,数据可视化),捕获这些跟踪数据,就能构建微服务的整个调用链的视图,这是调试和监控微服务的关键工具。
1. 相关术语:
- Span: 基本的工作单元。Span包括一个64位的唯一ID,一个64位trace码,描述信息,时间戳事件,key-value 注解(tags),span处理者的ID(通常为IP)。
- Trace: 包含一系列的工作单元span,它们组成了一个树型结构。
- Annotation 用于及时记录存在的事件。常用的Annotation如下:
cs:客户端发送(client send) 客户端发起一个请求,表示span开始;
sr:服务器接收(server received) 服务器接收到客户端的请求并开始处理,sr - cs 的时间为网络延迟;
ss:服务器发送(server send) 服务器处理完请求准备返回数据给客户端。ss - sr 的时间表示服务器端处理请求花费的时间;
cr:客户端接收(client received) 客户端接收到处理结果,表示span结束。 cr - cs 的时间表示客户端接收服务端数据的时间;
2. SpringCloudSleuth有4个特点
3.本文的案例组成:
- eureka_server :注册中心
- zipkin_service :本文核心内容zipkin
- sleuth_client_01 :服务提供
- sleuth_client_02 :服务调用
二、 Spring Cloud Sleuth 使用
关于 eureka-server 工程的搭建,可以参考:实现eureka 服务注册与发现 ,此处不在讲解。
1.创建Zipkin服务端子模块
Spring Boot2.0以后,官方不推荐我们自定义Zipkin服务端,而是使用官方提供的jar包。下载地址:
https://dl.bintray.com/openzipkin/maven/io/zipkin/java/zipkin-server/
这里我们不使用官方提供的jar包,方便我们以后扩展。
1. 创建 cloud_15_zipkin_server子模块
在子模块的pom 中添加如下依赖:
<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>
<!--zipkin-server 依赖包 -->
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-server</artifactId>
<version>2.11.7</version>
</dependency>
<dependency>
<groupId>io.zipkin.java</groupId>
<artifactId>zipkin-autoconfigure-ui</artifactId>
<version>2.11.7</version>
</dependency>
</dependencies>
2. 修改配置文件
配置文件application.yml 中的配置
server:
port: 9107
# spring config
spring:
application:
####注册中心应用名称
name: zipkin-server
main:
allow-bean-definition-overriding: true
## spring cloud eureka 注册中心
eureka:
client:
serviceUrl:
defaultZone: http://127.0.0.1:9090/eureka/
management:
metrics:
web:
server:
auto-time-requests: false
3. 在启动类上添加注解
在启动类上添加如下注解
@EnableZipkinServer //注解的作用: 开启zipkin功能
@EnableDiscoveryClient
@SpringBootApplication
public class CloudZipkinServerApplication {
public static void main(String[] args) {
SpringApplication.run(CloudZipkinServerApplication.class, args);
}
}
至此 zipkin 服务端创建完毕,依次启动:cloud_eureka_01 ,cloud_15_zipkin_server 。在地址栏访问:http://127.0.0.1:9107/zipkin/
2. 创建sleuth_client_01 客户端
创建子模块cloud_16_sleuth_server ,在子模块中的pom 文件中添加依赖.
1. 添加依赖。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--开启zipkin服务链路跟踪-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
</dependencies>
2. 修改配置文件
配置文件application.yml 中的配置
server:
port: 9108
spring:
application:
name: zipkin-client1
zipkin:
base-url: http://127.0.0.1:9107
eureka:
client:
serviceUrl:
defaultZone: http://localhost:9090/eureka/
3. 创建配置文件类
创建配置文件ZipkinClientConfig.java 类
@Configuration
public class ZipkinClientConfig {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
@Bean
public Sampler defaultSampler() {
return Sampler.ALWAYS_SAMPLE;
}
}
4. 在启动类上添加注解
在启动类上添加注解:@EnableDiscoveryClient
5. 通过控制类暴露接口
定义控制类如下:
@RestController
public class ZipkinClientController {
private static final Logger logger = Logger.getLogger(ZipkinClientController.class.getName());
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/hi")
public String callHome(){
logger.log(Level.INFO, "this is zipkin-client1!");
return restTemplate.getForObject("http://localhost:9109/miya", String.class);
}
@RequestMapping("/info")
public String info(){
logger.log(Level.INFO, "this is zipkin-client1!");
return "i'm zipkin-client1";
}
}
3. 创建 sleuth_client_02 客户端
创建cloud_17_sleuth_client 子模块,其创建过程同 cloud_16_sleuth_client,引入相同的依赖,配置 spring.zipkin.base-url 的URL 。
1. 修改配置文件
- 修改端口号;
- 修改应用名称;
server:
port: 9109
spring:
application:
name: zipkin-client2
zipkin:
base-url: http://127.0.0.1:9107
eureka:
client:
serviceUrl:
defaultZone: http://localhost:9090/eureka/
2. 在启动类上添加注解
在启动类上添加注解:@EnableDiscoveryClient
3. 修改控制类ZipkinClientController.java
@RestController
public class ZipkinClientController {
private static final Logger logger = Logger.getLogger(ZipkinClientController.class.getName());
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/hi")
public String callHome(){
logger.log(Level.INFO, "hi is sleuth_client_02");
return "hi i'm sleuth_client_02!";
}
@RequestMapping("/client_02")
public String info(){
logger.log(Level.INFO, "info is sleuth_client_02");
return restTemplate.getForObject("http://localhost:9108/info",String.class);
}
}
至此,四个服务已创建完成!
4. 启动工程,进行测试
依次启动:cloud_eureka_01 ,cloud_15_zipkin_server ,cloud_16_sleuth_client ,cloud_17_sleuth_client 四个子模块。
1. 在浏览器中输入:http://127.0.0.1:9107/zipkin/
2. 在浏览器中输入:http://127.0.0.1:9109/client_02 。
浏览器显示:
可以看到接口是成功调用的;
3. 继续访问zipkin服务端
再打开http://127.0.0.1:9107/zipkin/ 的界面,点击Dependencies,可以发现服务的依赖关系:
点击find a traces,可以进行筛选 查看具体服务相互调用的数据,查看每个接口请求的耗时时间、请求是否成功等。
点击某个服务还可以查看详情,可以看到调用链信息、trace id 、span id等,
至此,对Spring Cloud Sleuth 算是进行了入门级的学习。