Spring Boot 中如何使用 Spring Cloud Sleuth 来实现分布式跟踪?
在微服务架构中,通常会有多个服务相互协作,为了方便排查问题,我们需要对服务之间的调用进行跟踪。Spring Cloud Sleuth 是 Spring Cloud 生态中的分布式跟踪解决方案,它可以帮助我们追踪请求在微服务系统中的传递路径,以及记录每个服务的处理时间等信息。
本文将介绍如何在 Spring Boot 中使用 Spring Cloud Sleuth 来实现分布式跟踪。我们将使用 Zipkin 作为跟踪数据的存储和展示工具,并通过一个简单的示例来演示 Spring Cloud Sleuth 的使用。
准备工作
在开始本文之前,我们需要先准备以下环境:
- JDK 8 或以上版本
- Maven 3.2 或以上版本
- Zipkin Server
本文将使用 Spring Boot 2.5.1 和 Spring Cloud 2020.0.3 版本。
创建 Spring Boot 项目
首先,我们需要创建一个新的 Spring Boot 项目。可以使用 Spring Initializr 来快速创建项目,也可以手动创建项目。
使用 Spring Initializr 创建项目
访问 https://start.spring.io/,选择需要的配置项,如下图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZcZ10WlW-1684986080957)(null)]
然后点击 Generate 按钮,下载生成的项目压缩包。
手动创建项目
在本地创建一个空文件夹,然后在命令行中进入该文件夹,执行以下命令:
$ mkdir spring-cloud-sleuth-demo
$ cd spring-cloud-sleuth-demo
$ mkdir -p src/main/java/com/example/demo
$ mkdir -p src/main/resources
$ touch src/main/java/com/example/demo/DemoApplication.java
$ touch src/main/resources/application.properties
然后在 DemoApplication.java
文件中添加以下代码:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
在 application.properties
文件中添加以下配置:
spring.application.name=spring-cloud-sleuth-demo
server.port=8080
这里我们创建了一个名为 spring-cloud-sleuth-demo
的 Spring Boot 应用程序,并设置了应用程序的名称和端口号。
添加 Spring Cloud Sleuth 依赖
要使用 Spring Cloud Sleuth,我们需要在项目中添加以下依赖:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2020.0.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
</dependencies>
这里使用了 Spring Cloud 的依赖管理,以及 Spring Cloud Sleuth 的启动器依赖。
配置 Zipkin Server
Zipkin 是一个分布式跟踪系统,它可以显示跨多个服务的请求的跟踪信息。我们需要配置 Zipkin Server,以便在本地环境中使用它来存储和展示跟踪数据。
下载 Zipkin Server
首先,我们需要下载 Zipkin Server。可以从 https://zipkin.io/pages/quickstart.html 下载 Zipkin Server 的最新版。也可以使用以下命令下载和启动 Zipkin Server:
$ curl -sSL https://zipkin.io/quickstart.sh | bash -s
$ java -jar zipkin.jar
执行以上命令后,Zipkin Server 将启动在默认端口 9411 上。
配置 Spring Cloud Sleuth
要使用 Spring Cloud Sleuth,我们需要在 Spring Boot 应用程序的配置文件中添加以下配置:
spring.sleuth.sampler.probability=1.0
spring.zipkin.base-url=http://localhost:9411/
这里设置了采样率为 1.0,表示对所有的请求都进行采样。同时,指定了 Zipkin Server 的地址,以便将跟踪数据发送到 Zipkin Server。
编写示例代码
在本文中,我们将创建两个微服务,一个是 hello-service
,另一个是 world-service
。hello-service
会调用 world-service
,并在调用结束后返回结果。
创建 hello-service
创建一个名为 hello-service
的 Spring Boot应用程序。在 pom.xml
文件中添加以下依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
这里除了 Spring Cloud Sleuth 的依赖之外,还添加了 OpenFeign 的依赖,以便调用 world-service
。
在 application.properties
文件中添加以下配置:
spring.application.name=hello-service
server.port=8081
然后创建一个名为 Greeting
的类,用于表示返回的结果:
public class Greeting {
private String message;
public Greeting() {
}
public Greeting(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
接下来创建一个名为 HelloController
的类,用于接收请求并调用 world-service
:
@RestController
public class HelloController {
@Autowired
private WorldClient worldClient;
@GetMapping("/hello")
public Greeting sayHello(@RequestParam String name) {
String worldMessage = worldClient.getWorldMessage();
String message = String.format("Hello, %s! %s", name, worldMessage);
return new Greeting(message);
}
}
这里使用了 @Autowired
注解自动注入了 WorldClient
,并在 sayHello
方法中调用了 worldClient.getWorldMessage()
方法,获取 world-service
的响应结果,并将结果与 Hello, ${name}!
拼接为最终的返回结果。
最后,创建一个名为 WorldClient
的接口,并使用 @FeignClient
注解标记该接口,以便使用 OpenFeign 进行远程调用:
@FeignClient(name = "world-service")
public interface WorldClient {
@GetMapping("/world")
String getWorldMessage();
}
这里使用了 @FeignClient
注解,指定了被调用的服务名为 world-service
,并定义了一个 getWorldMessage
方法用于获取 world-service
的响应结果。
创建 world-service
创建一个名为 world-service
的 Spring Boot 应用程序。在 pom.xml
文件中添加以下依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
</dependencies>
这里只添加了 Spring Cloud Sleuth 的依赖。
在 application.properties
文件中添加以下配置:
spring.application.name=world-service
server.port=8082
然后创建一个名为 WorldController
的类,用于接收请求并返回响应:
@RestController
public class WorldController {
@GetMapping("/world")
public String sayWorld() {
return "World!";
}
}
这里只是简单地返回了一个字符串 “World!”。
测试分布式跟踪
在完成以上步骤后,我们可以启动 hello-service
和 world-service
,并访问 http://localhost:8081/hello?name=John
,可以看到返回结果为 Hello, John! World!
。
此时,我们可以通过访问 Zipkin Server 的 Web 界面来查看分布式跟踪数据。在浏览器中输入 http://localhost:9411/zipkin/
,然后点击 Find Traces
按钮,可以看到所有的跟踪数据,如下图所示:
可以看到,hello-service
和 world-service
都被成功地追踪到了,并且可以查看它们之间的调用关系和耗时等信息。
总结
本文介绍了如何在 Spring Boot 中使用 Spring Cloud Sleuth 来实现分布式跟踪。我们通过一个简单的示例演示了如何使用 Spring Cloud Sleuth 对微服务之间的调用进行跟踪,并使用 Zipkin 来存储和展示跟踪数据。
使用 Spring Cloud Sleuth 不仅可以方便地排查问题,同时也可以帮助我们了解微服务系统的性能瓶颈和瓶颈所在服务,从而更好地优化系统。