Spring Cloud Sleath
16.1 简介
- 在大规模分布式系统中,一个完整的系统是由很多不同的服务共同支撑的。不同的系统可能分布在上千台服务器上,横跨多个数据中心,一旦系统出现问题,此时定位就比较麻烦,这个时候就需要分布式链路追踪
- 在微服务环境下,中型的互联网公司,一次请求涉及的服务间调用可能由上百次,一旦请求出问题,需要考虑很多东西:
如何快速定位问题
如何快速确定此次请求,都涉及到哪些服务
到底是那个服务出现问题 - 要解决这些问题就涉及到分布式链路追踪
分布式链路追踪系统主要用了跟踪服务局调用记录,一步来说,一个分布式链路系统,由三个部分:
数据收集
数据存储
数据展示
Spring Cloud Sleath 是收集数据的部分,有点像 actuator。 - Sleath 是 Spring Cloud 提供的一套分布式链路追踪系统。有三个概念
trace:从请求到底系统开始,到给请求做出相应,这样一个过程是一个 trace
span:一次请求,可能有服务端之间的多次调用,每次调用服务时,埋入的一个调用记录,称为 span,是 64 位标记,是 trace 的单元
annotation:相当于 span 记录的语法,描述 span 所处的状态
16.2 简单应用
- 1.创建一个 Spring Boot 项目,引入 Spring Cloud Sleath ,添加 Sleath 和 Web 依赖
- 2.创建一个 HelloController,打印日志
@RestController
public class HelloController {
private static final Logger logger = LoggerFactory.getLogger(HelloController.class);
@GetMapping("/hello")
public String hello(){
logger.info("hello");
return "hello spring cloud sleuth!";
}
}
- 3.启动项目,访问 /hello 接口
在控制台的日志中,我们看见INFO [,bd30485f2adf37b4,bd30485f2adf37b4]
的日志内容,我找了一个没有加 Sleath 依赖的项目,打印日志是这样:
比没有添加 Sleath 的日志在 INFO 后面增加了[]
的内容 - 4.在 application.properties 中配置系统名称
spring.application.name=javaboy-sleath
- 5.再次执行相同的操作,在控制台日志如下:
[javaboy-sleath,a887171e64477723,a887171e64477723]
中
javaboy-sleath 是 application.properties 中配置的 spring.application.name 属性;
第一个 a887171e64477723 是 trace 的一个 spanId 的简写,表示当前服务的标记
第二个 a887171e64477723 是子 spanId,表示请求链路关系,相等表示是同一个服务。
- 6.调用链
在 HelloContriller 中定义三个接口,其中一个接口调用另一个接口,另一个接口调用最后一个接口,形成调用链,接口名是 /helo2 、 /hello3 和 /hello4
@RestController
public class HelloController {
private static final Logger logger = LoggerFactory.getLogger(HelloController.class);
@Autowired
RestTemplate restTemplate;
@GetMapping("/hello")
public String hello(){
logger.info("hello");
return "hello spring cloud sleuth!";
}
@GetMapping("/hello2")
public String hello2(){
logger.info("hello2");
return restTemplate.getForObject("http://localhost:8080/hello3",String.class);
}
@GetMapping("/hello3")
public String hello3(){
logger.info("hello3");
return restTemplate.getForObject("http://localhost:8080/hello4",String.class);
}
@GetMapping("/hello4")
public String hello4(){
logger.info("hello4");
return "hello4";
}
}
- 5.重启项目,访问 /hello2 接口验证接口调用情况
一个 trace 由多个 span 组成,一个 trace 相当于一个调用链,而 span 是这个链中每一次调用过程
最后上一张图解释哪个是 traceId,哪个是 spanId。