Spring Cloud Sleuth(分布式服务跟踪)(1)

- 日理万妓 2022-05-08 06:48 327阅读 0赞

首先准备工作如下:

1.服务注册中心:eureka-server。

2.微服务应用:trace-1,实现REST接口,并调用trace-2应用的接口。

其pom.xml文件如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <groupId>com.example</groupId>
  6. <artifactId>trace-1</artifactId>
  7. <version>0.0.1-SNAPSHOT</version>
  8. <packaging>jar</packaging>
  9. <name>trace-1</name>
  10. <description>Demo project for Spring Boot</description>
  11. <parent>
  12. <groupId>org.springframework.boot</groupId>
  13. <artifactId>spring-boot-starter-parent</artifactId>
  14. <version>2.0.5.RELEASE</version>
  15. <relativePath/> <!-- lookup parent from repository -->
  16. </parent>
  17. <properties>
  18. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  19. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  20. <java.version>1.8</java.version>
  21. <spring-cloud.version>Finchley.SR1</spring-cloud.version>
  22. </properties>
  23. <dependencies>
  24. <dependency>
  25. <groupId>org.springframework.boot</groupId>
  26. <artifactId>spring-boot-starter-web</artifactId>
  27. </dependency>
  28. <dependency>
  29. <groupId>org.springframework.cloud</groupId>
  30. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  31. </dependency>
  32. <dependency>
  33. <groupId>org.springframework.cloud</groupId>
  34. <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
  35. </dependency>
  36. <dependency>
  37. <groupId>org.springframework.boot</groupId>
  38. <artifactId>spring-boot-starter-test</artifactId>
  39. <scope>test</scope>
  40. </dependency>
  41. </dependencies>
  42. <dependencyManagement>
  43. <dependencies>
  44. <dependency>
  45. <groupId>org.springframework.cloud</groupId>
  46. <artifactId>spring-cloud-dependencies</artifactId>
  47. <version>${spring-cloud.version}</version>
  48. <type>pom</type>
  49. <scope>import</scope>
  50. </dependency>
  51. </dependencies>
  52. </dependencyManagement>
  53. <build>
  54. <plugins>
  55. <plugin>
  56. <groupId>org.springframework.boot</groupId>
  57. <artifactId>spring-boot-maven-plugin</artifactId>
  58. </plugin>
  59. </plugins>
  60. </build>
  61. </project>

应用主类如下:

  1. @RestController
  2. @EnableDiscoveryClient
  3. @SpringBootApplication
  4. public class Trace1Application {
  5. private final Logger logger=Logger.getLogger(getClass());
  6. @Bean
  7. @LoadBalanced
  8. RestTemplate restTemplate(){
  9. return new RestTemplate();
  10. }
  11. @GetMapping("/trace-1")
  12. public String trace(){
  13. logger.info("--------------------------- trace1 ----------------------------------");
  14. return restTemplate().getForEntity("http://trace-2/trace-2",String.class).getBody();
  15. }
  16. public static void main(String[] args) {
  17. SpringApplication.run(Trace1Application.class, args);
  18. }
  19. }

application.properties文件如下:

  1. spring.application.name=trace-1
  2. server.port=9101
  3. eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

3.创建第二个微服务应用:trace-2,实现REST接口/trace-2。

其pom.xml跟trace-1的pom文件相同。

应用主类如下:

  1. @RestController
  2. @EnableDiscoveryClient
  3. @SpringBootApplication
  4. public class Trace2Application {
  5. private final Logger logger=Logger.getLogger(getClass());
  6. @GetMapping("/trace-2")
  7. public String trace(){
  8. logger.info("--------------------------- trace2 ----------------------------------");
  9. return "Trace2";
  10. }
  11. public static void main(String[] args) {
  12. SpringApplication.run(Trace2Application.class, args);
  13. }
  14. }

application.properties文件如下:

  1. spring.application.name=trace-2
  2. server.port=9102
  3. eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

启动三个服务后调用http://localhost:9101/trace-1

70

70 1

70 2

实现跟踪

首先在trace-1和trace-2的pom.xml文件中加入spring-cloud-starter-sleuth依赖:

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

然后访问http://localhost:9101/trace-1

70 3

70 4

第一个值:trace-1,它记录了应用的名称(application.properties中的spring.application.name参数配置的属性。)

第二个值:13a031b537091ddc,Spring Cloud Sleuth生成的一个ID,称为Trace ID,它用来标示一条请求链路。一条请求链路中包含一个Trace ID,多个Span ID。

第三个值:13a031b537091ddc,Spring Cloud Sleuth生成的另外一个ID,称为Span ID,他表示一个基本的工作单元,比如发送一个HTTP请求。

第四个值:false,表示是否要将该信息输出到Zipkin等服务中来收集和展示。

上面的Trace ID和Span ID是Spring Cloud Sleuth实现分布式服务跟踪的核心。在一次服务请求链路的调用中,会保持传递同一个Trace ID,从而将整个分布于不同微服务进程中的请求跟踪信息串联在一起。

跟踪原理

分布式系统中的服务跟踪在理论上实现不复杂,它主要有两个关键点:

1.为了实现请求跟踪,当请求发送到分布式系统的入口端点时,只需要服务跟踪框架为该请求创建一个唯一的跟踪标识,同时在分布式系统内部流转的时候,框架始终保持传递该唯一标识,直到返回给请求方为止,这个唯一标识就是前文中提到的 TraceID。通过 TraceID的记录,我们就能将所有请求过程日志关联起来。

2.为了统计各处理单元的时间延迟,当请求达到各个服务组件时,或是处理逻辑到达某个状态时,也通过一个唯一标识来标记它的开始、具体过程以及结束,该标识就是我们前文中提到的Span ID,对于每个Span来说,它必须有开始和结束两个节点,通过记录开始Span和结束Span的时间戳,就能统计出该Span的时间延迟,除了时间戳记录之外,它还可以包含一些其他元数据,比如:事件名称、请求信息等。

在Spring Boot应用中,通过在工程中引入spring-cloud-starter-sleuth依赖之后,它会自动为当前应用构建起各通信通道的跟踪机制,如:

1.通过RabbitMQ,Kafka传递请求

2.通过Zuul代理传递的请求

3.通过RestTemplate发起的请求

查看源码可以获取:

  • X-B3-TraceId:一条请求链路(Trace)的唯一标识,必须值
  • X-B3-SpanId:一个工作单元(Span)的唯一标识,必须值
  • X-B3-ParentSpanId::标识当前工作单元所属的上一个工作单元,Root Span(请求链路的第一个工作单元)的该值为空
  • X-B3-Sampled:是否被抽样输出的标志,1表示需要被输出,0表示不需要被输出
  • X-Span-Name:工作单元的名称

修改trace-2的实现:

  1. @RestController
  2. @EnableDiscoveryClient
  3. @SpringBootApplication
  4. public class Trace2Application {
  5. private final Logger logger = Logger.getLogger(getClass());
  6. @GetMapping("/trace-2")
  7. public String trace(HttpServletRequest request) {
  8. logger.info("--------------------------- trace2 ----------------------------------");
  9. logger.infof(" \n TraceId={} \n SpanId={} \n ParentSpanId={} \n Sampled={} \n Name={}"
  10. , request.getHeader("X-B3-TraceId")
  11. , request.getHeader("X-B3-SpanId")
  12. , request.getHeader("X-B3-ParentSpanId")
  13. , request.getHeader("X-B3-Sampled")
  14. , request.getHeader("X-Span-Name"));
  15. return "Trace2";
  16. }
  17. public static void main(String[] args) {
  18. SpringApplication.run(Trace2Application.class, args);
  19. }
  20. }

70 5

70 6

为了更直观的观察跟踪信息,可以在application.properties增加如下配置:

  1. logging.level.org.springframework.web.servlet.DispatcherServlet=DEBUG

参考《Spring Cloud微服务实战》

发表评论

表情:
评论列表 (有 0 条评论,327人围观)

还没有评论,来说两句吧...

相关阅读