文章目录
基础使用
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.yml
或 application.properties
进行一些自定义配置。
spring:
sleuth:
sampler:
probability: 1.0 # 采样率,1.0 表示全部采样
3. 传递自定义数据
Spring Cloud Sleuth 默认会传递 Trace ID 和 Span ID,但你可以通过 Tracer
和 Baggage
来传递自定义数据。
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 头传递。
例如,如果你使用 RestTemplate
或 WebClient
来调用其他服务,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 和自定义数据。你可以使用 Tracer
和 Baggage
来增强追踪信息,并通过 RestTemplate
或 WebClient
自动传递上下文到下游服务。
BagageField使用
BaggageField
是 Spring Cloud Sleuth 提供的一个工具,用于在分布式追踪过程中传递自定义的上下文信息(即 baggage)。与 Trace ID
和 Span ID
不同,Baggage
是用户自定义的键值对,可以在整个调用链中传递,并且可以跨服务边界。
BaggageField
提供了一种线程安全的方式来管理和操作这些自定义的上下文信息。
1. BaggageField
的作用
- 传递自定义数据:可以在调用链中传递自定义的键值对。
- 线程安全:
BaggageField
是线程安全的,可以在多线程环境中使用。 - 自动传播:当使用 Sleuth 支持的 HTTP 客户端(如
RestTemplate
或WebClient
)时,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 客户端(如 RestTemplate
或 WebClient
)时,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
,你可以增强系统的可观测性和调试能力。