Spring Cloud Sleuth“操作方法”指南

时间:2022-12-02 17:06:36

Spring Cloud Sleuth“操作方法”指南

本节提供了一些常见的“我该怎么做...”问题的答案,这些问题在使用Spring Cloud Sleuth时经常出现。 它的覆盖范围并不详尽,但确实涵盖了相当多的内容。

如果您有我们此处未涵盖的特定问题,您可能需要查看*.com以查看是否有人已经提供了答案。 堆栈溢出也是提出新问题的好地方(请使用标签)。​​spring-cloud-sleuth​

我们也非常乐意扩展此部分。 如果您想添加“操作方法”,请向我们发送拉取请求。

1. 如何用勇敢设置侦探?

将侦探初学者添加到类路径中。

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

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

2. 如何通过HTTP使用Brave和Zipkin设置侦探?

将侦探入门和 Zipkin 添加到类路径中。

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

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

3. 如何通过消息传递与勇敢和齐普金一起设置侦探?

如果要使用 RabbitMQ、Kafka 或 ActiveMQ 而不是 HTTP,请添加 ordependency。 默认目标名称为。​​spring-rabbit​​​​spring-kafka​​​​org.apache.activemq:activemq-client​​​​Zipkin​

如果使用 Kafka,则必须添加 Kafka 依赖项。

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

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

此外,您需要相应地设置属性属性:​​spring.zipkin.sender.type​

spring.zipkin.sender.type: kafka

如果你想在 RabbitMQ 上侦探,请添加 和依赖项。​​spring-cloud-starter-sleuth​​​​spring-cloud-sleuth-zipkin​​​​spring-rabbit​

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

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

如果你想在ActiveMQ上侦探,添加,和依赖关系。​​spring-cloud-starter-sleuth​​​​spring-cloud-sleuth-zipkin​​​​activemq-client​

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

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-client</artifactId>
</dependency>

此外,您需要相应地设置属性属性:​​spring.zipkin.sender.type​

spring.zipkin.sender.type: activemq

4. 如何查看外部系统中的跨度?

如果您看不到跨度被报告给外部系统(例如 Zipkin),则很可能是由于以下原因:

  • 未对您的跨度进行采样
  • 您忘记添加依赖项以报告给外部系统(例如 spring-cloud-sleuth-zipkin)
  • 您错误地配置了与外部系统的连接

4.1. 您的跨度未被采样

为了检查是否未对跨度进行采样,只需查看是否设置了可导出标志即可。 让我们看下面的例子:

2020-10-21 12:01:16.285  INFO [backend,0b6aaf642574edd3,0b6aaf642574edd3,true] 289589 --- [nio-9000-exec-1] Example              : Hello world!

如果部分中的布尔值意味着正在对跨度进行采样,应报告。​​[backend,0b6aaf642574edd3,0b6aaf642574edd3,true]​​​​true​

4.2. 缺少依赖

直到Sleuth 3.0.0,依赖关系包括依赖关系和依赖关系。 删除了 3.0.0,因此您需要将其更改为。​​spring-cloud-starter-zipkin​​​​spring-cloud-starter-sleuth​​​​spring-cloud-sleuth-zipkin​​​​spring-cloud-starter-zipkin​​​​spring-cloud-sleuth-zipkin​

4.3. 连接配置错误

仔细检查远程系统地址是否正确(例如),以及如果尝试通过代理进行通信,您的代理连接是否已正确设置。​​spring.zipkin.baseUrl​

5. 如何制作 RestTemplate、WebClient 等工作?

如果您观察到跟踪上下文未被传播,则原因为以下原因之一:

  • 我们不是在检测给定的库
  • 我们正在检测库,但是您错误地配置了设置

如果缺少检测功能,请提交问题并请求添加此类检测。

如果配置错误,请确保您用于通信的客户端是 Spring bean。 如果通过操作员手动创建客户端,则检测将不起作用。​​new​

检测将起作用的示例:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration(proxyBeanMethods = false)
class MyConfiguration {
@Bean RestTemplate myRestTemplate() {
return new RestTemplate();
}
}

@Service
class MyService {
private final RestTemplate restTemplate;

MyService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}

String makeACall() {
return this.restTemplate.getForObject("http://example.com", String.class);
}

}

检测不起作用的示例:

@Service
class MyService {

String makeACall() {
// This will not work because RestTemplate is not a bean
return new RestTemplate().getForObject("http://example.com", String.class);
}

}

6. 如何在HTTP服务器响应中添加标头?

注册将设置服务器响应的筛选器。

import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;

import javax.servlet.Filter;
import org.springframework.web.server.WebFilter;

@Configuration(proxyBeanMethods = false)
class MyConfig {

// Example of a servlet Filter for non-reactive applications
@Bean
Filter traceIdInResponseFilter(Tracer tracer) {
return (request, response, chain) -> {
Span currentSpan = tracer.currentSpan();
if (currentSpan != null) {
HttpServletResponse resp = (HttpServletResponse) response;
// putting trace id value in [mytraceid] response header
resp.addHeader("mytraceid", currentSpan.context().traceId());
}
chain.doFilter(request, response);
};
}

// Example of a reactive WebFilter for reactive applications
@Bean
WebFilter traceIdInResponseFilter(Tracer tracer) {
return (exchange, chain) -> {
Span currentSpan = tracer.currentSpan();
if (currentSpan != null) {
// putting trace id value in [mytraceid] response header
exchange.getResponse().getHeaders().add("mytraceid", currentSpan.context().traceId());
}
return chain.filter(exchange);
};
}
}

需要对跨度进行采样,解析器才能正常工作。这意味着您需要能够将跨度导出到例如 Zipkin。

7. 如何自定义 HTTP 客户端跨度?

注册一个 bean 类型,其名称是为请求端添加自定义。 注册一个 bean 类型,其名称是为响应端添加自定义。​​HttpRequestParser​​​​HttpClientRequestParser.NAME​​​​HttpResponseParser​​​​HttpClientRequestParser.NAME​

@Configuration(proxyBeanMethods = false)
public static class ClientParserConfiguration {

// example for Feign
@Bean(name = HttpClientRequestParser.NAME)
HttpRequestParser myHttpClientRequestParser() {
return (request, context, span) -> {
// Span customization
span.name(request.method());
span.tag("ClientRequest", "Tag");
Object unwrap = request.unwrap();
if (unwrap instanceof feign.Request) {
feign.Request req = (feign.Request) unwrap;
// Span customization
span.tag("ClientRequestFeign", req.httpMethod().name());
}
};
}

// example for Feign
@Bean(name = HttpClientResponseParser.NAME)
HttpResponseParser myHttpClientResponseParser() {
return (response, context, span) -> {
// Span customization
span.tag("ClientResponse", "Tag");
Object unwrap = response.unwrap();
if (unwrap instanceof feign.Response) {
feign.Response resp = (feign.Response) unwrap;
// Span customization
span.tag("ClientResponseFeign", String.valueOf(resp.status()));
}
};
}

}

8. 如何自定义 HTTP 服务器跨度?

注册一个 bean 类型,其名称是为请求端添加自定义。 注册一个 bean 类型,其名称是为响应端添加自定义。​​HttpRequestParser​​​​HttpServerRequestParser.NAME​​​​HttpResponseParser​​​​HttpServerResponseParser.NAME​

@Configuration(proxyBeanMethods = false)
public static class ServerParserConfiguration {

@Bean(name = HttpServerRequestParser.NAME)
HttpRequestParser myHttpRequestParser() {
return (request, context, span) -> {
// Span customization
span.tag("ServerRequest", "Tag");
Object unwrap = request.unwrap();
if (unwrap instanceof HttpServletRequest) {
HttpServletRequest req = (HttpServletRequest) unwrap;
// Span customization
span.tag("ServerRequestServlet", req.getMethod());
}
};
}

@Bean(name = HttpServerResponseParser.NAME)
HttpResponseParser myHttpResponseParser() {
return (response, context, span) -> {
// Span customization
span.tag("ServerResponse", "Tag");
Object unwrap = response.unwrap();
if (unwrap instanceof HttpServletResponse) {
HttpServletResponse resp = (HttpServletResponse) unwrap;
// Span customization
span.tag("ServerResponseServlet", String.valueOf(resp.getStatus()));
}
};
}

@Bean
Filter traceIdInResponseFilter(Tracer tracer) {
return (request, response, chain) -> {
Span currentSpan = tracer.currentSpan();
if (currentSpan != null) {
HttpServletResponse resp = (HttpServletResponse) response;
resp.addHeader("mytraceid", currentSpan.context().traceId());
}
chain.doFilter(request, response);
};
}

}

需要对跨度进行采样,解析器才能正常工作。这意味着您需要能够将跨度导出到例如 Zipkin。

9. 如何在日志中查看应用程序名称?

假设您尚未更改默认日志记录格式,请将属性设置为 in,而不是 in。​​spring.application.name​​​​bootstrap.yml​​​​application.yml​

10. 如何改变上下文传播机制?

要使用提供的默认值,您可以设置该属性。 该值可以是列表,在这种情况下,您将传播更多跟踪标头。​​spring.sleuth.propagation.type​

对于勇敢,我们支持,传播类型。​​AWS​​​​B3​​​​W3C​

如果要提供自定义传播机制,请将属性设置为并实现自己的 bean(对于 Brave)。 您可以在下面找到示例:​​spring.sleuth.propagation.type​​​​CUSTOM​​​​Propagation.Factory​

@Component
class CustomPropagator extends Propagation.Factory implements Propagation<String> {

@Override
public List<String> keys() {
return Arrays.asList("myCustomTraceId", "myCustomSpanId");
}

@Override
public <R> TraceContext.Injector<R> injector(Setter<R, String> setter) {
return (traceContext, request) -> {
setter.put(request, "myCustomTraceId", traceContext.traceIdString());
setter.put(request, "myCustomSpanId", traceContext.spanIdString());
};
}

@Override
public <R> TraceContext.Extractor<R> extractor(Getter<R, String> getter) {
return request -> TraceContextOrSamplingFlags.create(TraceContext.newBuilder()
.traceId(HexCodec.lowerHexToUnsignedLong(getter.get(request, "myCustomTraceId")))
.spanId(HexCodec.lowerHexToUnsignedLong(getter.get(request, "myCustomSpanId"))).build());
}

@Override
public <K> Propagation<K> create(KeyFactory<K> keyFactory) {
return StringPropagationAdapter.create(this, keyFactory);
}

}

11. 如何实现我自己的示踪剂?

Spring Cloud Sleuth API 包含跟踪器要实现的所有必要接口。 该项目带有OpenZipkin Brave实现。 您可以通过查看模块来检查两个跟踪器如何桥接到侦探的 API。​​org.springframework.cloud.sleuth.brave.bridge​