Spring Cloud Sleuth 集成
1. 异步通信
在本节中,我们将介绍如何使用 Spring Cloud Sleuth 自定义异步通信。
1.1.@Async带注释的方法
此功能适用于所有跟踪器实现。
在 Spring Cloud Sleuth 中,我们检测异步相关组件,以便跟踪信息在线程之间传递。您可以通过设置spring.sleuth.async.enabled自false.
如果使用@Async,我们自动修改现有 Span,如下所示:
-
如果该方法用
@SpanName,则注释的值是 Span 的名称。 -
如果该方法未使用
@SpanName,则 Span 名称是带注释的方法名称。 -
span 使用方法的类名和方法名进行标记。
由于我们正在修改现有的 span,如果您想保留其原始名称(例如,通过接收 HTTP 请求创建的 span)您应该将@Async带有 annotated 的方法,其中包含@NewSpan注释或手动创建新跨度。
1.2.@Scheduled带注释的方法
此功能适用于所有跟踪器实现。
在 Spring Cloud Sleuth 中,我们检测计划的方法执行,以便跟踪信息在线程之间传递。您可以通过设置spring.sleuth.scheduled.enabled自false.
如果使用@Scheduled,我们会自动创建一个具有以下特征的新跨度:
-
span 名称是带注释的方法名称。
-
span 使用方法的类名和方法名进行标记。
如果您想跳过某些跨度创建@ScheduledCommentted 类,您可以将spring.sleuth.scheduled.skipPattern使用与@Scheduled带注释的类。
1.3. Executor、ExecutorService 和 ScheduledExecutorService
此功能适用于所有跟踪器实现。
我们提供LazyTraceExecutor,TraceableExecutorService和TraceableScheduledExecutorService. 这些实现在每次提交、调用或计划新任务时都会创建跨度。
以下示例演示如何使用TraceableExecutorService使用CompletableFuture:
CompletableFuture<Long> completableFuture = CompletableFuture.supplyAsync(() -> {
// perform some logic
return 1_000_000L;
}, new TraceableExecutorService(beanFactory, executorService,
// 'calculateTax' explicitly names the span - this param is optional
"calculateTax"));
侦探不适用于parallelStream()开箱即用。如果要通过流传播跟踪信息,则必须将该方法与supplyAsync(…),如前所述。 |
如果有实现Executor要从 span 创建中排除的接口,您可以使用spring.sleuth.async.ignored-beans属性,您可以在其中提供 bean 名称列表。
您可以通过将spring.sleuth.async.enabled自false.
1.3.1. 执行器的自定义
有时,您需要设置AsyncExecutor. 以下示例演示如何设置此类自定义Executor:
@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
@EnableAsync
// add the infrastructure role to ensure that the bean gets auto-proxied
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public static class CustomExecutorConfig extends AsyncConfigurerSupport {
@Autowired
BeanFactory beanFactory;
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// CUSTOMIZE HERE
executor.setCorePoolSize(7);
executor.setMaxPoolSize(42);
executor.setQueueCapacity(11);
executor.setThreadNamePrefix("MyExecutor-");
// DON'T FORGET TO INITIALIZE
executor.initialize();
return new LazyTraceExecutor(this.beanFactory, executor);
}
}
为确保配置得到后处理,请记住将@Role(BeanDefinition.ROLE_INFRASTRUCTURE)在您的@Configuration类 |
2. HTTP 客户端集成
可以通过设置spring.sleuth.web.client.enabled值等于false.
2.1. 同步休息模板
此功能适用于所有跟踪器实现。
我们注入一个RestTemplate拦截器,以确保将所有跟踪信息传递给请求。每次进行调用时,都会创建一个新的 Span。它在收到响应后关闭。阻止同步RestTemplate功能, 设置spring.sleuth.web.client.enabled自false.
您必须注册RestTemplate作为 bean ,以便注入拦截器。如果您创建RestTemplate实例与new关键字,则检测不起作用。 |
2.2. 异步休息模板
此功能适用于所有跟踪器实现。
从侦探开始2.0.0,我们不再注册AsyncRestTemplate类型。 由你来创造这样的豆子。然后我们对其进行检测。 |
要阻止AsyncRestTemplate功能, 设置spring.sleuth.web.async.client.enabled自false. 禁用创建默认值TraceAsyncClientHttpRequestFactoryWrapper设置spring.sleuth.web.async.client.factory.enabled自false. 如果您不想创建AsyncRestClient完全,设置spring.sleuth.web.async.client.template.enabled自false.
2.2.1. 多个异步 Rest 模板
有时你需要使用异步 Rest 模板的多个实现。
在以下代码段中,您可以看到如何设置此类自定义的示例AsyncRestTemplate:
@Configuration(proxyBeanMethods = false)
public static class TestConfig {
@Bean(name = "customAsyncRestTemplate")
public AsyncRestTemplate traceAsyncRestTemplate() {
return new AsyncRestTemplate(asyncClientFactory(), clientHttpRequestFactory());
}
private ClientHttpRequestFactory clientHttpRequestFactory() {
ClientHttpRequestFactory clientHttpRequestFactory = new CustomClientHttpRequestFactory();
// CUSTOMIZE HERE
return clientHttpRequestFactory;
}
private AsyncClientHttpRequestFactory asyncClientFactory() {
AsyncClientHttpRequestFactory factory = new CustomAsyncClientHttpRequestFactory();
// CUSTOMIZE HERE
return factory;
}
}
2.2.2.WebClient
此功能适用于所有跟踪器实现。
我们注入一个ExchangeFilterFunction创建跨度的实现,并通过成功时和错误时回调来关闭客户端跨度。
要阻止此功能,请将spring.sleuth.web.client.enabled自false.
您必须注册WebClient作为 bean,以便应用跟踪检测。
如果您创建WebClient实例与new关键字,则检测不起作用。 |
2.2.3. 特拉弗森
此功能适用于所有跟踪器实现。
如果使用 Traverson 库,则可以注入RestTemplate作为 Bean 放入 Traverson 对象中。
因为RestTemplate已经被拦截,则您可以在客户端中获得对跟踪的全面支持。
以下伪代码显示了如何执行此作:
@Autowired RestTemplate restTemplate;
Traverson traverson = new Traverson(URI.create("https://some/address"),
MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON_UTF8).setRestOperations(restTemplate);
// use Traverson
2.2.4. 阿帕奇HttpClientBuilder和HttpAsyncClientBuilder
此功能可用于 Brave 示踪剂的实现。
我们检测HttpClientBuilder和HttpAsyncClientBuilder以便将跟踪上下文注入到发送的请求中。
要阻止这些功能,请将spring.sleuth.web.client.enabled自false.
2.2.5. 内蒂HttpClient
此功能适用于所有跟踪器实现。
我们检测 Netty 的HttpClient.
要阻止此功能,请将spring.sleuth.web.client.enabled自false.
您必须注册HttpClient作为 bean,以便进行检测。
如果您创建HttpClient实例与new关键字,则检测不起作用。 |
2.2.6.UserInfoRestTemplateCustomizer
此功能适用于所有跟踪器实现。
我们检测 Spring Security 的UserInfoRestTemplateCustomizer.
要阻止此功能,请将spring.sleuth.web.client.enabled自false.
3. HTTP服务器集成
可以通过设置spring.sleuth.web.enabled值等于false.
3.1. HTTP 过滤器
此功能适用于所有跟踪器实现。
通过TracingFilter,则所有采样的传入请求都会导致创建 Span。
您可以通过设置spring.sleuth.web.skipPattern财产。
如果您有ManagementServerProperties在类路径上,其值contextPath附加到提供的跳过模式。
如果你想重用 Sleuth 的默认跳过模式,而只是附加你自己的跳过模式,请使用spring.sleuth.web.additionalSkipPattern.
默认情况下,所有 Spring Boot 执行器端点都会自动添加到跳过模式中。
如果您想禁用此行为集spring.sleuth.web.ignore-auto-configured-skip-patterns自true.
要更改跟踪过滤器注册的顺序,请将spring.sleuth.web.filter-order财产。
若要禁用记录未捕获异常的筛选器,可以禁用spring.sleuth.web.exception-throwing-filter-enabled财产。
3.2. Handler拦截器
此功能适用于所有跟踪器实现。
由于我们希望 span 名称精确,因此我们使用TraceHandlerInterceptor包装现有的HandlerInterceptor或直接添加到现有列表中HandlerInterceptors.
这TraceHandlerInterceptor将特殊请求属性添加到给定的HttpServletRequest.
如果TracingFilter看不到此属性,它会创建一个“回退”范围,这是在服务器端创建的附加范围,以便在 UI 中正确显示跟踪。
如果发生这种情况,则可能缺少仪器。
在这种情况下,请在 Spring Cloud Sleuth 中提交问题。
3.3. 异步 Servlet 支持
此功能适用于所有跟踪器实现。
如果您的控制器返回Callable或WebAsyncTask,Spring Cloud Sleuth 继续现有的 span,而不是创建一个新的 span。
3.4. WebFlux 支持
此功能适用于所有跟踪器实现。
通过TraceWebFilter,则所有采样的传入请求都会导致创建 Span。
那个 Span 的名字是http:+ 请求发送到的路径。
例如,如果请求发送到/this/that,名称是http:/this/that.
您可以使用spring.sleuth.web.skipPattern财产。
如果您有ManagementServerProperties在类路径上,其值contextPath附加到提供的跳过模式。
如果你想重用 Sleuth 的默认跳过模式并附加你自己的跳过模式,请使用spring.sleuth.web.additionalSkipPattern.
为了在性能和上下文传播方面获得最佳结果,我们建议您将spring.sleuth.reactor.instrumentation-type自MANUAL.
为了执行范围内具有 span 的代码,您可以调用WebFluxSleuthOperators.withSpanInScope.
例:
@GetMapping("/simpleManual")
public Mono<String> simpleManual() {
return Mono.just("hello").map(String::toUpperCase).doOnEach(WebFluxSleuthOperators
.withSpanInScope(SignalType.ON_NEXT, signal -> log.info("Hello from simple [{}]", signal.get())));
}
要更改跟踪过滤器注册的顺序,请将spring.sleuth.web.filter-order财产。
4. 消息传递
可以通过设置spring.sleuth.messaging.enabled值等于false.
4.1. Spring 集成
此功能适用于所有跟踪器实现。
Spring Cloud Sleuth 与 Spring Integration 集成。
它为发布和订阅事件创建跨度。
要禁用 Spring Integration 检测,请将spring.sleuth.integration.enabled自false.
您可以提供spring.sleuth.integration.patternspattern 以显式提供要包括用于跟踪的通道的名称。
默认情况下,所有通道hystrixStreamOutput频道都包括在内。
使用Executor构建 Spring IntegrationIntegrationFlow,则必须使用Executor.
使用TraceableExecutorService导致跨度关闭不当。 |
如果要自定义从消息头读取和写入跟踪上下文的方式,只需注册以下类型的 bean:
-
Propagator.Setter<MessageHeaderAccessor>- 用于将标题写入邮件 -
Propagator.Getter<MessageHeaderAccessor>- 用于从邮件中读取标题
4.1.2. 自定义消息传递范围
为了更改默认的 span 名称和标签,只需注册一个MessageSpanCustomizer.您还可以
覆盖现有的DefaultMessageSpanCustomizer以扩展现有行为。
@Component
class MyMessageSpanCustomizer extends DefaultMessageSpanCustomizer {
@Override
public Span customizeHandle(Span spanCustomizer,
Message<?> message, MessageChannel messageChannel) {
return super.customizeHandle(spanCustomizer, message, messageChannel)
.name("changedHandle")
.tag("handleKey", "handleValue")
.tag("channelName", channelName(messageChannel));
}
@Override
public Span.Builder customizeSend(Span.Builder builder,
Message<?> message, MessageChannel messageChannel) {
return super.customizeSend(builder, message, messageChannel)
.name("changedSend")
.tag("sendKey", "sendValue")
.tag("channelName", channelName(messageChannel));
}
}
4.2. Spring Cloud 函数和 Spring Cloud Stream
此功能适用于所有跟踪器实现。
Spring Cloud Sleuth 可以检测 Spring Cloud 函数。
实现它的方法是提供一个Function或Consumer或Supplier它采用Message作为参数,例如Function<Message<String>, Message<Integer>>.
如果类型不是Message则不会进行仪器测试。
在处理基于 Reactor 的流时,不会进行开箱即用的检测 - 例如Function<Flux<Message<String>>, Flux<Message<Integer>>>.
由于 Spring Cloud Stream 重用了 Spring Cloud Function,因此您将开箱即用。
您可以通过将spring.sleuth.function.enabled自false.
为了使用响应式流函数,您可以利用MessagingSleuthOperators实用程序类,允许您作输入和输出消息,以便继续跟踪上下文并在跟踪上下文中执行自定义代码。
class SimpleReactiveManualFunction implements Function<Flux<Message<String>>, Flux<Message<String>>> {
private static final Logger log = LoggerFactory.getLogger(SimpleReactiveFunction.class);
private final BeanFactory beanFactory;
SimpleReactiveManualFunction(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Override
public Flux<Message<String>> apply(Flux<Message<String>> input) {
return input.map(message -> (MessagingSleuthOperators.asFunction(this.beanFactory, message))
.andThen(msg -> MessagingSleuthOperators.withSpanInScope(this.beanFactory, msg, stringMessage -> {
log.info("Hello from simple manual [{}]", stringMessage.getPayload());
return stringMessage;
})).andThen(msg -> MessagingSleuthOperators.afterMessageHandled(this.beanFactory, msg, null))
.andThen(msg -> MessageBuilder.createMessage(msg.getPayload().toUpperCase(), msg.getHeaders()))
.andThen(msg -> MessagingSleuthOperators.handleOutputMessage(this.beanFactory, msg)).apply(message));
}
}
4.3. 春兔Mq
此功能可用于 Brave 示踪剂的实现。
我们检测RabbitTemplate以便将跟踪标头注入到消息中。
要阻止此功能,请将spring.sleuth.messaging.rabbit.enabled自false.
4.4. Spring的卡夫卡
此功能可用于 Brave 示踪剂的实现。
我们检测 Spring Kafka 的ProducerFactory和ConsumerFactory以便将跟踪标头注入到创建的 Spring Kafka 的Producer和Consumer.
要阻止此功能,请将spring.sleuth.messaging.kafka.enabled自false.
4.5. Spring Kafka 流
此功能可用于 Brave 示踪剂的实现。
我们检测KafkaStreams KafkaClientSupplier以便将跟踪标头注入到Producer和Consumer`s. A `KafkaStreamsTracingbean 允许通过额外的TransformerSupplier和ProcessorSupplier方法。
要阻止此功能,请将spring.sleuth.messaging.kafka.streams.enabled自false.
4.6. 弹簧JMS
此功能可用于 Brave 示踪剂的实现。
我们检测JmsTemplate以便将跟踪标头注入到消息中。
我们还支持@JmsListener消费者端的带注释的方法。
要阻止此功能,请将spring.sleuth.messaging.jms.enabled自false.
| 我们不支持 JMS 的包传 |
5. 开放伪装
此功能适用于所有跟踪器实现。
默认情况下,Spring Cloud Sleuth 通过TraceFeignClientAutoConfiguration.
您可以通过设置spring.sleuth.feign.enabled自false. 如果这样做,则不会发生与 Feign 相关的检测。
部分 Feign 检测是通过FeignBeanPostProcessor. 您可以通过设置spring.sleuth.feign.processor.enabled自false. 如果将其设置为false,Spring Cloud Sleuth 不会检测您的任何自定义 Feign 组件。但是,所有默认检测仍然存在。
6. 开放追踪
此功能适用于所有跟踪器实现。
Spring Cloud Sleuth 与 OpenTracing 兼容。如果您在类路径上有 OpenTracing,我们会自动注册 OpenTracingTracer豆。 如果要禁用此功能,请将spring.sleuth.opentracing.enabled自false
7. Quartz
此功能适用于所有跟踪器实现。
我们通过将 Job/Trigger 监听器添加到 Quartz Scheduler 来检测 Quartz 作业。
要关闭此功能,请将spring.sleuth.quartz.enabled属性设置为false.
8. 反应堆
此功能适用于所有跟踪器实现。
我们有以下基于反应堆的应用程序的检测模式,可以通过spring.sleuth.reactor.instrumentation-type财产:
-
DECORATE_QUEUES- 通过新的 Reactor 队列包装机制(Reactor 3.4.3),我们正在检测 Reactor 切换线程的方式。这应该导致功能与ON_EACH对性能影响小。 -
DECORATE_ON_EACH- 将每个 Reactor 运算符包装在跟踪表示中。 在大多数情况下传递跟踪上下文。 此模式可能会导致性能急剧下降。 -
DECORATE_ON_LAST- 将最后一个 Reactor 运算符包装在跟踪表示中。 在某些情况下传递跟踪上下文,因此访问 MDC 上下文可能不起作用。 此模式可能会导致中等性能下降。 -
MANUAL- 以侵入性最小的方式包装每个 Reactor,而无需传递跟踪上下文。 这取决于用户。
当前默认值为ON_EACH但是,出于向后兼容性的原因,我们鼓励用户迁移到MANUAL仪器和利润WebFluxSleuthOperators和MessagingSleuthOperators.
性能改进可能是可观的。
例:
@GetMapping("/simpleManual")
public Mono<String> simpleManual() {
return Mono.just("hello").map(String::toUpperCase).doOnEach(WebFluxSleuthOperators
.withSpanInScope(SignalType.ON_NEXT, signal -> log.info("Hello from simple [{}]", signal.get())));
}
9. Redis
此功能可用于 Brave 示踪剂的实现。
我们设置tracing属性到生菜ClientResources实例来启用 Lettuce 中内置的 Brave 跟踪。
Spring Cloud Sleuth 将提供ClientResources豆。如果您有自己的该 Bean 实现,请记住自定义ClientResources.Builder带有如下所示的“ClientResourcesBuilderCustomizer”流:
@Bean(destroyMethod = "shutdown")
DefaultClientResources myLettuceClientResources(ObjectProvider<ClientResourcesBuilderCustomizer> customizer) {
DefaultClientResources.Builder builder = DefaultClientResources.builder();
// setting up the builder manually
customizer.stream().forEach(c -> c.customize(builder));
return builder.build();
}
要禁用 Redis 支持,请将spring.sleuth.redis.enabled属性设置为false.
10. 可运行和可调用
此功能适用于所有跟踪器实现。
如果将逻辑包装在Runnable或Callable,您可以将这些类包装在其 Sleuth 代表中,如以下示例所示Runnable:
Runnable runnable = new Runnable() {
@Override
public void run() {
// do some work
}
@Override
public String toString() {
return "spanNameFromToStringMethod";
}
};
// Manual `TraceRunnable` creation with explicit "calculateTax" Span name
Runnable traceRunnable = new TraceRunnable(this.tracer, spanNamer, runnable, "calculateTax");
以下示例显示了如何对Callable:
Callable<String> callable = new Callable<String>() {
@Override
public String call() throws Exception {
return someLogic();
}
@Override
public String toString() {
return "spanNameFromToStringMethod";
}
};
// Manual `TraceCallable` creation with explicit "calculateTax" Span name
Callable<String> traceCallable = new TraceCallable<>(tracer, spanNamer, callable, "calculateTax");
这样,您就可以确保为每次执行创建和关闭一个新的跨度。
11. RPC
此功能可用于 Brave 示踪剂的实现。
Sleuth 会自动配置RpcTracingbean,它作为 RPC 检测的基础,例如 gRPC 或 Dubbo。
如果需要自定义 RPC 跟踪的客户端/服务器采样,只需注册一个类型为brave.sampler.SamplerFunction<RpcRequest>并命名 beansleuthRpcClientSampler用于客户端采样器和sleuthRpcServerSampler用于服务器采样器。
为方便起见,该@RpcClientSampler和@RpcServerSampler注释可用于注入正确的 bean 或通过其静态字符串引用 bean 名称NAME领域。
前任。 这是一个采样器,每秒跟踪 100 个“GetUserToken”服务器请求。 这不会为对运行状况检查服务的请求启动新的跟踪。 其他请求将使用全局采样配置。
@Configuration(proxyBeanMethods = false)
class Config {
@Bean(name = RpcServerSampler.NAME)
SamplerFunction<RpcRequest> myRpcSampler() {
Matcher<RpcRequest> userAuth = and(serviceEquals("users.UserService"), methodEquals("GetUserToken"));
return RpcRuleSampler.newBuilder().putRule(serviceEquals("grpc.health.v1.Health"), Sampler.NEVER_SAMPLE)
.putRule(userAuth, RateLimitingSampler.create(100)).build();
}
}
11.1. Dubbo RPC 支持
通过与 Brave 的集成,Spring Cloud Sleuth 支持 Dubbo。只需将brave-instrumentation-dubboDependency:
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-dubbo</artifactId>
</dependency>
您还需要设置一个dubbo.properties文件,其中包含以下内容:
dubbo.provider.filter=tracing
dubbo.consumer.filter=tracing
11.2. gRPC
Spring Cloud Sleuth 通过 Brave 跟踪器为 gRPC 提供检测。您可以通过将spring.sleuth.grpc.enabled自false.
11.2.1. 变体 1
依赖
| gRPC 集成依赖于两个外部库来检测客户端和服务器,并且这两个库都必须位于类路径上才能启用检测。 |
Maven:
<dependency>
<groupId>io.github.lognet</groupId>
<artifactId>grpc-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-grpc</artifactId>
</dependency>
Gradle:
compile("io.github.lognet:grpc-spring-boot-starter")
compile("io.zipkin.brave:brave-instrumentation-grpc")
服务器检测
Spring Cloud Sleuth 利用 grpc-spring-boot-starter 将 Brave 的 gRPC 服务器拦截器注册到所有带有@GRpcService.
客户端检测
gRPC 客户端利用ManagedChannelBuilder构造一个ManagedChannel用于与 gRPC 服务器通信。本机ManagedChannelBuilder提供静态方法作为构造ManagedChannel但是,此机制不受 Spring 应用程序上下文的影响。
Spring Cloud Sleuth 提供了一个SpringAwareManagedChannelBuilder可以通过 Spring 应用程序上下文进行自定义并由 gRPC 客户端注入。创建时必须使用此构建器ManagedChannel实例。
|
侦探创建了一个TracingManagedChannelBuilderCustomizer将 Brave 的客户端拦截器注入到SpringAwareManagedChannelBuilder.
11.2.2. 变体 2
Grpc Spring Boot Starter 会自动检测 Spring Cloud Sleuth 和 Brave 的 gRPC 检测的存在,并注册必要的客户端和/或服务器工具。
12. RxJava的
此功能适用于所有跟踪器实现。
我们注册一个自定义RxJavaSchedulersHook那将所有Action0实例,称为TraceAction. 挂钩开始或继续一个跨度,具体取决于在计划作之前是否已经在进行跟踪。禁用自定义RxJavaSchedulersHook,将spring.sleuth.rxjava.schedulers.hook.enabled自false.
您可以为不希望为其创建范围的线程名称定义正则表达式列表。为此,请在spring.sleuth.rxjava.schedulers.ignoredthreads财产。
| 建议的响应式编程和侦探方法是使用 Reactor 支持。 |
13. Spring Cloud 断路器
此功能适用于所有跟踪器实现。
如果类路径上有 Spring Cloud CircuitBreaker,我们将包装传递的命令Supplier和后备Function在其跟踪表示中。为了禁用此检测集spring.sleuth.circuitbreaker.enabled自false.