WEBKT

Spring Cloud Sleuth + Zipkin 微服务链路追踪实战:代码配置与可视化详解

28 0 0 0

一、技术选型与环境准备

二、项目结构设计

三、Zipkin Server 搭建

四、微服务改造

五、启动所有服务并测试

六、深入理解 Sleuth 和 Zipkin 的工作原理

七、高级配置与优化

八、总结

在微服务架构中,服务之间的调用关系错综复杂,一旦出现问题,排查起来犹如大海捞针。这时,链路追踪技术就显得尤为重要。Spring Cloud Sleuth 和 Zipkin 是目前流行的链路追踪解决方案,可以帮助我们清晰地了解请求在微服务之间的调用路径和耗时情况,从而快速定位问题。本文将以一个完整的示例,详细介绍如何使用 Spring Cloud Sleuth 和 Zipkin 来追踪微服务架构中的请求链路,并通过可视化界面查看调用关系和耗时情况。

一、技术选型与环境准备

  1. Spring Boot 版本:2.7.x 或更高版本(推荐最新稳定版)
  2. Spring Cloud 版本:2021.0.x 或更高版本(与 Spring Boot 版本对应)
  3. Zipkin 版本:2.23.x 或更高版本
  4. JDK 版本:1.8 或更高版本
  5. 构建工具:Maven 或 Gradle
  6. IDE:IntelliJ IDEA 或 Eclipse

二、项目结构设计

为了演示方便,我们创建一个包含三个微服务的简单应用:

  • service-a:接收外部请求,调用 service-b
  • service-b:接收 service-a 的请求,调用 service-c
  • service-c:接收 service-b 的请求,返回最终结果
  • zipkin-server: 负责收集和展示链路数据

项目结构如下:

microservice-tracing/
├── service-a/
│ ├── pom.xml
│ └── src/main/java/...
├── service-b/
│ ├── pom.xml
│ └── src/main/java/...
├── service-c/
│ ├── pom.xml
│ └── src/main/java/...
└── zipkin-server/
├── pom.xml
└── src/main/java/...

三、Zipkin Server 搭建

  1. 创建 zipkin-server 项目

    创建一个 Spring Boot 项目,命名为 zipkin-server

  2. 添加依赖

    pom.xml 中添加以下依赖:

    <dependencies>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin-server</artifactId>
    </dependency>
    </dependencies>
    <dependencyManagement>
    <dependencies>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>${spring-cloud.version}</version>
    <type>pom</type>
    <scope>import</scope>
    </dependency>
    </dependencies>
    </dependencyManagement>

    确保 spring-cloud.version 与你的 Spring Cloud 版本一致。

  3. 配置 Zipkin Server

    application.propertiesapplication.yml 中添加以下配置:

    server.port=9411
    spring.application.name=zipkin-server
    # 使用内存存储,生产环境建议使用持久化存储(如 Elasticsearch, Cassandra)
    zipkin.storage.type=mem
    
  4. 启动 Zipkin Server

    在主类上添加 @EnableZipkinServer 注解,启动 Zipkin Server。

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import zipkin2.server.internal.EnableZipkinServer;
    @SpringBootApplication
    @EnableZipkinServer
    public class ZipkinServerApplication {
    public static void main(String[] args) {
    SpringApplication.run(ZipkinServerApplication.class, args);
    }
    }

    启动成功后,访问 http://localhost:9411,即可看到 Zipkin 的 Web UI。

四、微服务改造

service-aservice-bservice-c 进行如下改造:

  1. 创建 Spring Boot 项目

    分别创建三个 Spring Boot 项目,命名为 service-aservice-bservice-c

  2. 添加依赖

    在每个项目的 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-zipkin</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    </dependencies>
    <dependencyManagement>
    <dependencies>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>${spring-cloud.version}</version>
    <type>pom</type>
    <scope>import</scope>
    </dependency>
    </dependencies>
    </dependencyManagement>
    • spring-boot-starter-web:提供 Web 服务能力
    • spring-cloud-starter-sleuth:链路追踪的核心组件
    • spring-cloud-starter-zipkin:将链路数据发送到 Zipkin Server
    • spring-cloud-starter-openfeign:声明式 HTTP 客户端,方便服务间调用
  3. 配置微服务

    在每个项目的 application.propertiesapplication.yml 中添加以下配置:

    service-a:

    server.port=8081
    spring.application.name=service-a
    # Zipkin Server 地址
    spring.zipkin.baseUrl=http://localhost:9411
    # 采样率,1.0 表示全部采样
    spring.sleuth.sampler.probability=1.0
    

    service-b:

    server.port=8082
    spring.application.name=service-b
    spring.zipkin.baseUrl=http://localhost:9411
    spring.sleuth.sampler.probability=1.0
    

    service-c:

    server.port=8083
    spring.application.name=service-c
    spring.zipkin.baseUrl=http://localhost:9411
    spring.sleuth.sampler.probability=1.0
    
    • server.port:服务端口
    • spring.application.name:服务名称,用于在 Zipkin UI 中区分服务
    • spring.zipkin.baseUrl:Zipkin Server 的地址
    • spring.sleuth.sampler.probability:采样率,控制链路数据的采集比例。1.0 表示全部采样,生产环境可以根据实际情况调整,避免数据量过大。
  4. 使用 Feign 进行服务间调用

    a. 定义 Feign 客户端接口

    service-a 中定义一个 Feign 客户端接口,用于调用 service-b

    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    @FeignClient("service-b")
    public interface ServiceBClient {
    @GetMapping("/b")
    String callB();
    }
    • @FeignClient("service-b"):指定要调用的服务名称,需要与 service-bspring.application.name 一致。
    • @GetMapping("/b"):指定要调用的接口路径,需要与 service-b 的 Controller 接口路径一致。

    同样,在 service-b 中定义一个 Feign 客户端接口,用于调用 service-c

    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    @FeignClient("service-c")
    public interface ServiceCClient {
    @GetMapping("/c")
    String callC();
    }

    b. 启用 Feign 客户端

    service-aservice-b 的启动类上添加 @EnableFeignClients 注解,启用 Feign 客户端。

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.openfeign.EnableFeignClients;
    @SpringBootApplication
    @EnableFeignClients
    public class ServiceAApplication {
    public static void main(String[] args) {
    SpringApplication.run(ServiceAApplication.class, args);
    }
    }

    c. 注入 Feign 客户端并调用

    service-a 的 Controller 中注入 ServiceBClient 并调用:

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    @RestController
    public class ServiceAController {
    @Autowired
    private ServiceBClient serviceBClient;
    @GetMapping("/a")
    public String callA() {
    return "Service A -> " + serviceBClient.callB();
    }
    }

    service-b 的 Controller 中注入 ServiceCClient 并调用:

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    @RestController
    public class ServiceBController {
    @Autowired
    private ServiceCClient serviceCClient;
    @GetMapping("/b")
    public String callB() {
    return "Service B -> " + serviceCClient.callC();
    }
    }
  5. 创建 Controller

    service-c 中创建一个简单的 Controller,返回一个字符串:

    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    @RestController
    public class ServiceCController {
    @GetMapping("/c")
    public String callC() {
    return "Service C";
    }
    }

五、启动所有服务并测试

  1. 启动 Zipkin Server

  2. 启动 service-a、service-b 和 service-c

  3. 访问 service-a 的接口

    在浏览器中访问 http://localhost:8081/a,如果一切正常,应该看到类似如下的输出:

    Service A -> Service B -> Service C
    
  4. 查看 Zipkin UI

    访问 http://localhost:9411,点击 “Find Traces” 按钮,即可看到链路追踪数据。

    在 Zipkin UI 中,你可以看到:

    • 请求在各个微服务之间的调用关系
    • 每个调用的耗时情况
    • 请求的详细信息,如 HTTP 方法、URL、Headers 等

六、深入理解 Sleuth 和 Zipkin 的工作原理

  • Sleuth:负责生成和传播 Trace ID 和 Span ID。Trace ID 标识一个完整的请求链路,Span ID 标识链路中的一个调用单元。Sleuth 会自动将 Trace ID 和 Span ID 添加到 HTTP Headers 中,以便在服务间传递。
  • Zipkin:负责收集、存储和展示链路数据。Zipkin Agent 负责将链路数据发送到 Zipkin Collector,Zipkin Collector 将数据存储到 Zipkin Storage 中,Zipkin UI 从 Zipkin Storage 中读取数据并展示。

七、高级配置与优化

  1. 持久化存储

    默认情况下,Zipkin Server 使用内存存储,数据会丢失。生产环境建议使用持久化存储,如 Elasticsearch, Cassandra 等。可以通过配置 zipkin.storage.type 来指定存储类型,并配置相应的连接信息。

    例如,使用 Elasticsearch 存储:

    zipkin.storage.type=elasticsearch
    spring.elasticsearch.rest.uris=http://localhost:9200
    
  2. 调整采样率

    spring.sleuth.sampler.probability 用于控制采样率。如果微服务数量较多,请求量较大,可以适当降低采样率,避免数据量过大。但需要注意的是,采样率过低可能会导致部分链路数据丢失。

  3. 自定义 Span

    Sleuth 默认会追踪 HTTP 请求、数据库操作等。如果需要追踪其他操作,可以使用 @NewSpan 注解自定义 Span。

    import org.springframework.cloud.sleuth.annotation.NewSpan;
    public class MyService {
    @NewSpan("myCustomSpan")
    public void doSomething() {
    // ...
    }
    }

八、总结

本文详细介绍了如何使用 Spring Cloud Sleuth 和 Zipkin 来追踪微服务架构中的请求链路,并通过可视化界面查看调用关系和耗时情况。链路追踪是微服务架构中不可或缺的一部分,可以帮助我们快速定位问题,提高系统的可维护性和可观测性。希望本文能够帮助你更好地理解和使用 Spring Cloud Sleuth 和 Zipkin。

通过本文的示例,你应该能够:

  • 搭建 Zipkin Server
  • 配置微服务,集成 Spring Cloud Sleuth 和 Zipkin
  • 使用 Feign 进行服务间调用
  • 在 Zipkin UI 中查看链路追踪数据
  • 理解 Sleuth 和 Zipkin 的工作原理
  • 进行高级配置与优化,如持久化存储、调整采样率、自定义 Span

掌握这些知识,你就可以在自己的微服务项目中应用链路追踪技术,提升系统的可观测性和可维护性。

TracingPro Spring Cloud SleuthZipkin微服务链路追踪

评论点评

打赏赞助
sponsor

感谢您的支持让我们更好的前行

分享

QRcode

https://www.webkt.com/article/10047