java—是否可以在completablefuture#SupplySync中提供不同的默认执行器?

kmbjn2e3  于 2021-07-06  发布在  Java
关注(0)|答案(0)|浏览(390)

我目前正在向一个项目添加分布式跟踪。但是,跟踪范围使用线程局部变量来存储跟踪上下文,例如。 traceId 或者 spanId . 因此,无论何时创建 CompletableFuture 您需要用一个“可跟踪”的执行器来 Package 它的执行器,该执行器将这些变量传递给新线程。
Spring Boot提供了这样的 Package 。
以上链接中的建议如下:

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"));

我想避免创建一个新的 TraceableExecutorServiceCompletableFuture 我创造。主要原因是1)这会造成大量代码重复,2)我需要注入 BeanFactory 如果有人忘记添加 Package 器,跟踪就会中断。
到目前为止,我已经找到了三种解决方案,但并不理想:
使用此上下文传播库。虽然这可能有效(几个月前我测试了这个库,不记得我是否成功地使它工作了),但它仍然受到来自上面的3的影响。你需要记住导入 nl.talsmasoftware.context.futures.ContextAwareCompletableFuture 而不是典型的java CompletableFuture ,否则跟踪将不起作用。
创建一个小 Package 。这也有同样的问题。如果忘记使用 Package 器,跟踪将停止工作。
向项目中添加一个静态代码分析工具,检查您是否使用过典型的java CompletableFuture#supplyAsync .
我做的 Package 是这样的:

@Service
public class TraceAwareCompletableFutureFactory implements CompletableFutureFactory {

  private final BeanFactory beanFactory;
  private final Executor defaultExecutor;

  public TraceAwareCompletableFutureFactory(BeanFactory beanFactory) {
    this.beanFactory = beanFactory;
    this.defaultExecutor = wrap(ForkJoinPool.commonPool());
  }

  @Override
  public <T> CompletableFuture<T> supplyAsync(Supplier<T> supplier) {
    return supplyAsync(supplier, defaultExecutor);
  }

  @Override
  public <T> CompletableFuture<T> supplyAsync(Supplier<T> supplier, Executor executor) {
    return CompletableFuture.supplyAsync(supplier, wrap(executor));
  }

  private Executor wrap(Executor executor) {
    return new LazyTraceExecutor(beanFactory, executor);
  }
}

我一直在想,解决这三个问题的一个办法就是以某种方式违约 CompletableFuture#supplyAsync 使用不同的默认执行器。在看 CompletableFuture 的代码,这是不可能的。 supplyAsync 是静态方法并获取其默认值 Executorprivate static 变量。
有没有办法做这样的事?你能提出一个替代我的解决方案吗?

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题