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 使用方法的类名和方法名进行标记。
如果您想跳过某些跨度创建@Scheduled
Commentted 类,您可以将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.patterns
pattern 以显式提供要包括用于跟踪的通道的名称。
默认情况下,所有通道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 `KafkaStreamsTracing
bean 允许通过额外的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 会自动配置RpcTracing
bean,它作为 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-dubbo
Dependency:
<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
.