在微服务架构中,一个请求可能会经过多个微服务的处理,这就意味着当我们要对系统进行性能分析或故障排查时,需要追踪一个请求在不同服务间的传递。Spring Cloud Sleuth是Spring Cloud提供的分布式追踪解决方案,它通过在服务间传递唯一的追踪ID,可以清晰地追踪请求流程和定位潜在的性能问题。
引入依赖
首先,我们需要在项目的pom.xml文件中引入spring-cloud-starter-sleuth
依赖,以使用Spring Cloud Sleuth:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
配置
接下来,我们需要对服务的配置文件进行一些调整,以开启和配置Spring Cloud Sleuth。
添加配置项
在应用的application.properties
或application.yml
文件中,添加以下配置项:
spring:
sleuth:
sampler:
probability: 1.0 # 配置采样概率,默认为0.1,设置为1表示采样100%
通过调整sampler.probability
的值,可以灵活地控制请求的采样率。默认情况下,Spring Cloud Sleuth会根据sampler.probability
的值随机决定是否对某个请求进行采样。
添加日志标志
为了在日志中打印相关的追踪信息,我们还需要在logback.xml
(或其他日志配置文件)中添加一些标志,例如:
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level [${springAppName:-},%X{X-Trace-Id:-},%X{X-Span-Id:-},%X{X-Span-Export:-}] %logger:%L - %msg%n</pattern>
</encoder>
</appender>
该配置用于在日志中打印追踪ID(Trace Id)、跨度ID(Span Id)和是否导出(Span Export)等信息。我们可以通过在请求头中传递这些信息来实现链路追踪。
调用其他服务
为了在服务间传递追踪信息,我们需要在调用其他服务时,将追踪ID添加到请求头中。
RestTemplate方式
如果我们在应用中使用RestTemplate来调用其他服务,可以使用RestTemplateInterceptor
来自动在请求头中添加追踪ID。首先,创建一个拦截器:
import brave.propagation.ExtraFieldPropagation;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpResponse;
import java.io.IOException;
public class RestTemplateInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
request.getHeaders().add("X-Trace-Id", ExtraFieldPropagation.get("X-Trace-Id"));
request.getHeaders().add("X-Span-Id", ExtraFieldPropagation.get("X-Span-Id"));
request.getHeaders().add("X-Span-Export", ExtraFieldPropagation.get("X-Span-Export"));
return execution.execute(request, body);
}
}
然后,在配置类中将该拦截器添加到RestTemplate的拦截器列表中:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getInterceptors().add(new RestTemplateInterceptor());
return restTemplate;
}
}
现在,当我们使用RestTemplate调用其他服务时,会自动在请求头中添加追踪ID。
Feign方式
如果我们在应用中使用Feign来调用其他服务,可以通过创建一个Feign拦截器的方式在请求头中添加追踪ID。首先,创建一个拦截器:
import brave.propagation.ExtraFieldPropagation;
import feign.RequestInterceptor;
import feign.RequestTemplate;
public class FeignInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
requestTemplate.header("X-Trace-Id", ExtraFieldPropagation.get("X-Trace-Id"));
requestTemplate.header("X-Span-Id", ExtraFieldPropagation.get("X-Span-Id"));
requestTemplate.header("X-Span-Export", ExtraFieldPropagation.get("X-Span-Export"));
}
}
然后,通过注解将该拦截器添加到Feign的配置类中:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfig {
@Bean
public FeignInterceptor feignInterceptor() {
return new FeignInterceptor();
}
}
现在,当我们使用Feign调用其他服务时,会自动在请求头中添加追踪ID。
链路追踪
在配置好Spring Cloud Sleuth后,我们就可以开始链路追踪了。
首先,在我们的代码中打印日志,以便我们可以在日志中查看追踪信息。例如:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class ExampleController {
private static final Logger LOGGER = LoggerFactory.getLogger(ExampleController.class);
@GetMapping("/example")
public String example() {
LOGGER.info("Received request");
return "Hello, World!";
}
}
当我们发送一个请求到/api/example
接口时,在日志中会显示类似以下内容的追踪信息:
15:30:45.123 [http-nio-8080-exec-1] INFO [example-service,f805f58030ccd3fa,a7c86188f8c217c5,false] com.example.controller.ExampleController:32 - Received request
在这个例子中,我们可以看到追踪ID(f805f58030ccd3fa),跨度ID(a7c86188f8c217c5)和是否导出(false)的信息。
总结
通过使用Spring Cloud Sleuth,我们可以轻松地实现分布式追踪和链路追踪。它使我们能够在微服务架构中准确地追踪请求的流程,并更方便地进行性能分析和故障排查。希望这篇博客对你理解和使用Spring Cloud Sleuth有所帮助!
本文来自极简博客,作者:代码魔法师,转载请注明原文链接:如何使用Spring Cloud Sleuth进行分布式追踪