将 AWS Java SDK 2.x 与 Spring Sleuth 集成

我是第一次使用 Spring Boot,并且正在为我的应用程序设置分布式跟踪。我已将 Spring Cloud Slueth 添加到我的应用程序中,我可以看到在调用我的端点时生成的跨度和跟踪,但是我很难让它与 Aws Sdk 2.x 集成(使用 Dynamo 异步客户端)。我有几个关于集成的问题:

  1. 通过 aws sdk 跟踪 http 调用的最佳方法是什么。我能够做到的唯一方法是实现 ExecutionInterceptor 并手动创建一个跨度:
@Component
@Log4j2
public class AwsExecutionInterceptor implements ExecutionInterceptor {
    public static final String CLIENT_CALL_SPAN = "ClientCallSpan";
    public static final ExecutionAttribute<Span> ATTRIBUTE = new ExecutionAttribute<>(
            CLIENT_CALL_SPAN);
    private final Tracer tracer;

    @Autowired
    public AwsExecutionInterceptor(Tracer tracer) {
        this.tracer = tracer;
    }

    @Override
    public void beforeExecution(Context.BeforeExecution context,ExecutionAttributes executionAttributes) {

        Span clientCallSpan = this.tracer.nextSpan().name("clientCall").start();
        log.info("Starting new span");
        executionAttributes.putAttribute(ATTRIBUTE,clientCallSpan);
    }

    @Override
    public void afterExecution(Context.AfterExecution context,ExecutionAttributes executionAttributes) {
        Span span = executionAttributes.getattribute(ATTRIBUTE);
        span.end();
        log.info("Span closed");
    }
}
  1. 有没有办法让跟踪 ID 从通过 aws sdk 记录的 netty 线程池传播到日志?我通过高级选项提供了一个执行程序,但跟踪不会从 netty 线程传播到日志。下面是一个例子:
public class AwsExecutorConfig {

    @Bean("AwsClientExecutor")
    public Executor executor() {

        ThreadPoolExecutor executor = new ThreadPoolExecutor(50,50,10,TimeUnit.SECONDS,new LinkedBlockingQueue<>(10_000));

        executor.allowCoreThreadTimeOut(true);
        return executor;
    }
}
@Autowired
public DynamoConfig(AwsExecutionInterceptor executionInterceptor,@Qualifier("AwsClientExecutor") Executor executor) {

  @Bean(destroyMethod = "close")
  public DynamoDbAsyncClient dynamoDbAsyncClient() {
    var builder = DynamoDbAsyncClient.builder();
    builder.overrideConfiguration(
        ClientOverrideConfiguration.builder()
                                   .addExecutionInterceptor(executionInterceptor).build());

    builder.asyncConfiguration(
            b -> b.advancedOption(SdkAdvancedAsyncClientOption.FUTURE_COMPLETION_EXECUTOR,executor));
    return builder.build();
  }
}

这样,我可以从 sdk 中看到如下日志,

2021-07-20 10:26:04.369 DEBUG [,c9ae653fd2254266,c9ae653fd2254266] 2873 --- [pool-2-thread-5] s.a.a.m.internal.DefaultMetricCollector  : Collected metrics records: MetricCollection(...)

但其他日志没有任何痕迹,例如:

2021-07-20 10:26:04.360 DEBUG [,] 2873 --- [tyEventLoop-0-2] software.amazon.awssdk.request           : Received successful response: 200
2021-07-20 10:26:04.361 TRACE [,] 2873 --- [tyEventLoop-0-2] software.amazon.awssdk.request           : Parsing service response JSON.
2021-07-20 10:26:04.361 DEBUG [,] 2873 --- [tyEventLoop-0-2] software.amazon.awssdk.requestId         : x-amzn-RequestId : af0d9968-3202-480f-9e3c-8312ae6963c8
2021-07-20 10:26:04.361 DEBUG [,] 2873 --- [tyEventLoop-0-2] software.amazon.awssdk.requestId         : x-amz-id-2 : not available
2021-07-20 10:26:04.367 TRACE [,] 2873 --- [tyEventLoop-0-2] software.amazon.awssdk.request           : Done parsing service response.

spring cloud sleuth 文档提到了与 Netty Http 客户端的集成,但我不确定如何使用 AWS SDK 做到这一点。对此的任何帮助将不胜感激

skywwh123 回答:将 AWS Java SDK 2.x 与 Spring Sleuth 集成

这是一个非常重要的问题,让我尝试为您提供一些背景知识并解释您可以做什么/寻找什么。

Spring Cloud Sleuth

Spring Cloud Sleuth 是对分布式跟踪库(如 OpenZipkin's Brave)的抽象。这意味着您可以使用 Sleuth 的 API 来检测您的代码,并且您可以在幕后更改您的跟踪库。这也意味着您可以使用您选择的跟踪库的内置检测(例如:您使用 Sleuth 检测您的代码,但您也可以添加 Brave 的 MySQL 检测,两者将协同工作)。

(Brave 不是 Sleuth 支持的唯一跟踪库。Sleuth 也有 OTel 支持,但该支持尚未正式发布,因此我们不建议在生产中使用它。)

如何查找仪器支持

由于上述原因,您可以在几个地方查看检测支持:

  1. Spring Cloud Sleuth 检测了 Spring Framework 支持的一堆东西(AWS 不是那样的,Spring Cloud AWS 现在是一个社区支持的项目)但是正如你所说的 netty 客户端是:{{3} }
  2. Brave 有很多库的 docs,如果有任何可以重用的东西,你可以看看那里(例如:instrumentation support 中有一些 AWS 支持)
  3. 库本身可以有 Brave 支持(我认为 AWS 开发工具包目前不是这种情况)

如何自己检测事物

我建议使用 Sleuth API 来检测您的代码,您可以在此处找到方法:different repo。 如您所见,如果您想检测第三方库,这可能会很棘手,但您可以做以下几件事:

  1. 类似于你上面对拦截器所做的事情(假设有这样一个组件,你可以用它来注入你自己的代码)。仅供参考:您的实现不会创建“范围”,[参见文档](Creating and Ending Spans)。
  2. 您可以利用 AOP,创建一个 Aspect 并以这种方式注入检测逻辑(搜索“方面”Creating and Ending Spans)。
  3. 您可以创建一个包装器来执行检测并委托给检测的组件。您可以通过创建 bean 或使用 BeanPostProcessor(搜索“beanpostprocessor”here)来包装原始组件。

上下文传播到日志

here 通常通过将跟踪数据放入 MDC 发生,并且跟踪数据通常通过线程局部变量传播。因此,如果您在执行期间更改线程,您的跟踪数据就会丢失,并且在线程池中就像从头开始一个全新的跨度(没有父跨度)。幸运的是,Sleuth 有一个解决方案,您需要将 Executor 包装到 Sleuth 提供的组件中,Sleuth 会为您将上下文传播到您的线程池中,请参阅:log integration

Netty 的 HttpClient 问题

请检查 thread-pool support,它必须是一个 bean,以便 Sleuth 可以检测它。

本文链接:https://www.f2er.com/64577.html

大家都在问