【Spring相关知识】Spring Cloud Sleuth上下文信息传递

发布于:2025-02-15 ⋅ 阅读:(140) ⋅ 点赞:(0)

基础使用

Spring Cloud Sleuth 是一个用于分布式追踪的工具,它可以帮助你在微服务架构中传递上下文信息,如 Trace ID 和 Span ID。通过这些信息,你可以追踪请求在不同服务之间的流转情况。

1. 添加依赖

首先,你需要在 pom.xml 中添加 Spring Cloud Sleuth 的依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>

2. 配置 Sleuth

Spring Cloud Sleuth 会自动配置 Trace 和 Span 的生成和传递。你不需要额外的配置,但可以通过 application.ymlapplication.properties 进行一些自定义配置。

spring:
  sleuth:
    sampler:
      probability: 1.0  # 采样率,1.0 表示全部采样

3. 传递自定义数据

Spring Cloud Sleuth 默认会传递 Trace ID 和 Span ID,但你可以通过 TracerBaggage 来传递自定义数据。

3.1 使用 Tracer 传递自定义数据

你可以使用 Tracer 来创建自定义的 Span 并添加标签:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @Autowired
    private Tracer tracer;

    @GetMapping("/example")
    public String example() {
        // 创建一个新的 Span
        Span newSpan = tracer.nextSpan().name("custom-span").start();
        try (Tracer.SpanInScope ws = tracer.withSpan(newSpan.start())) {
            // 添加自定义标签
            newSpan.tag("custom-tag", "custom-value");
            // 业务逻辑
            return "Hello from example endpoint";
        } finally {
            newSpan.end();
        }
    }
}
3.2 使用 Baggage 传递自定义数据

Baggage 允许你在整个调用链中传递自定义数据。你可以在一个服务中设置 Baggage,然后在另一个服务中读取它。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.sleuth.BaggageInScope;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @Autowired
    private Tracer tracer;

    @GetMapping("/set-baggage")
    public String setBaggage() {
        // 设置 Baggage
        BaggageInScope baggage = tracer.createBaggage("custom-baggage-key");
        baggage.set("custom-baggage-value");
        return "Baggage set";
    }

    @GetMapping("/get-baggage")
    public String getBaggage() {
        // 获取 Baggage
        BaggageInScope baggage = tracer.getBaggage("custom-baggage-key");
        return "Baggage value: " + baggage.get();
    }
}

4. 跨服务传递上下文

Spring Cloud Sleuth 会自动将 Trace ID 和 Span ID 通过 HTTP 头传递到下游服务。如果你使用了 Baggage,它也会自动通过 HTTP 头传递。

例如,如果你使用 RestTemplateWebClient 来调用其他服务,Sleuth 会自动处理上下文的传递。

4.1 使用 RestTemplate
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class MyController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/call-downstream")
    public String callDownstream() {
        return restTemplate.getForObject("http://downstream-service/example", String.class);
    }
}
4.2 使用 WebClient
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;

@RestController
public class MyController {

    @Autowired
    private WebClient.Builder webClientBuilder;

    @GetMapping("/call-downstream")
    public String callDownstream() {
        return webClientBuilder.build()
                .get()
                .uri("http://downstream-service/example")
                .retrieve()
                .bodyToMono(String.class)
                .block();
    }
}

5. 总结

通过 Spring Cloud Sleuth,你可以轻松地在微服务架构中传递上下文信息,包括 Trace ID、Span ID 和自定义数据。你可以使用 TracerBaggage 来增强追踪信息,并通过 RestTemplateWebClient 自动传递上下文到下游服务。

BagageField使用

BaggageField 是 Spring Cloud Sleuth 提供的一个工具,用于在分布式追踪过程中传递自定义的上下文信息(即 baggage)。与 Trace IDSpan ID 不同,Baggage 是用户自定义的键值对,可以在整个调用链中传递,并且可以跨服务边界。

BaggageField 提供了一种线程安全的方式来管理和操作这些自定义的上下文信息。

1. BaggageField 的作用

  • 传递自定义数据:可以在调用链中传递自定义的键值对。
  • 线程安全BaggageField 是线程安全的,可以在多线程环境中使用。
  • 自动传播:当使用 Sleuth 支持的 HTTP 客户端(如 RestTemplateWebClient)时,BaggageField 的值会自动通过 HTTP 头传播到下游服务。

2. 使用 BaggageField 的步骤

2.1 创建 BaggageField

首先,你需要定义一个 BaggageField。通常可以在配置类中定义:

import org.springframework.cloud.sleuth.BaggageField;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SleuthConfig {

    @Bean
    public BaggageField customBaggageField() {
        return BaggageField.create("custom-baggage-key");
    }
}
2.2 设置和获取 BaggageField 的值

在代码中,你可以通过 BaggageField 设置和获取自定义的值。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.sleuth.BaggageField;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @Autowired
    private BaggageField customBaggageField;

    @GetMapping("/set-baggage")
    public String setBaggage() {
        // 设置 Baggage 的值
        customBaggageField.updateValue("custom-baggage-value");
        return "Baggage set to: " + customBaggageField.getValue();
    }

    @GetMapping("/get-baggage")
    public String getBaggage() {
        // 获取 Baggage 的值
        return "Baggage value: " + customBaggageField.getValue();
    }
}
2.3 跨服务传递 BaggageField

当使用 Sleuth 支持的 HTTP 客户端(如 RestTemplateWebClient)时,BaggageField 的值会自动通过 HTTP 头传递到下游服务。

例如,使用 RestTemplate

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class MyController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private BaggageField customBaggageField;

    @GetMapping("/call-downstream")
    public String callDownstream() {
        // 设置 Baggage 的值
        customBaggageField.updateValue("custom-baggage-value");

        // 调用下游服务
        return restTemplate.getForObject("http://downstream-service/example", String.class);
    }
}

在下游服务中,你可以通过相同的 BaggageField 获取传递的值:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.sleuth.BaggageField;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DownstreamController {

    @Autowired
    private BaggageField customBaggageField;

    @GetMapping("/example")
    public String example() {
        // 获取 Baggage 的值
        return "Received baggage value: " + customBaggageField.getValue();
    }
}

3. 配置 BaggageField 的传播

默认情况下,BaggageField 的值会通过 HTTP 头传播到下游服务。你可以通过配置来控制哪些 BaggageField 需要传播。

application.yml 中配置:

spring:
  sleuth:
    baggage:
      remote-fields: custom-baggage-key  # 指定需要传播的 BaggageField

4. 注意事项

  • 性能影响:传递过多的 BaggageField 可能会影响性能,因为每个 HTTP 请求都会携带这些额外的头信息。
  • 大小限制:HTTP 头的大小是有限制的,通常为 8KB。如果 BaggageField 的值过大,可能会导致请求失败。
  • 安全性:不要在 BaggageField 中传递敏感信息,因为这些信息会以明文形式传递。

5. 完整示例

服务 A(上游服务)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.sleuth.BaggageField;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class MyController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private BaggageField customBaggageField;

    @GetMapping("/call-downstream")
    public String callDownstream() {
        // 设置 Baggage 的值
        customBaggageField.updateValue("custom-baggage-value");

        // 调用下游服务
        return restTemplate.getForObject("http://downstream-service/example", String.class);
    }
}
服务 B(下游服务)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.sleuth.BaggageField;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DownstreamController {

    @Autowired
    private BaggageField customBaggageField;

    @GetMapping("/example")
    public String example() {
        // 获取 Baggage 的值
        return "Received baggage value: " + customBaggageField.getValue();
    }
}

总结

BaggageField 是 Spring Cloud Sleuth 提供的一个强大工具,用于在分布式系统中传递自定义的上下文信息。通过合理使用 BaggageField,你可以增强系统的可观测性和调试能力。


网站公告

今日签到

点亮在社区的每一天
去签到