Resilience4j:将 Bulkhead 与 TimeLimiter 相结合,用于来自 Tomcat 的同步外部系统调用

Resilience4j: Combine Bulkhead with TimeLimiter for a synchronous external system call from Tomcat

我在 Tomcat 服务器中有一个 Web 应用程序 运行,它执行对外部服务器的调用。 现在,我想使用 Resilience4j 的 TimeLimiter 来限制响应的等待时间,另外还想使用 Bulkhead 来限制对外部服务器的并行调用量。

我不需要对外部系统进行异步调用,因为 Tomcat 线程无论如何都必须等待响应或超时。

在这种情况下,结合 TimeLimiterBulkhead 的最佳方法是什么?我需要 SemaphoreBulkhead 还是 ThreadPoolBulkhead 以及如何将我的外部系统调用包装在 TimeLimiter 所需的 Future 中?

您不能组合 SemaphoreBulkhead 和 TimeLimiter,因为如果 运行 同一个线程,TimeLimiter 无法停止任务的执行。

因此您只能组合一个TimeLimiter 和一个ThreadPoolBulkhead。但只有当你想要一个 non-blocking/async 代码而不阻塞你的线程时才有意义。

如果你想要屏蔽代码,你可以使用:

CompletableFuture.supplyAsync(() -> service.method()).get(1, TimeUnit.SECONDS);

如果您想要非阻塞代码并且可以使用 Java9 或更高版本,您可以这样做:

CompletableFuture.supplyAsync(() -> service.method()).orTimeout(1, TimeUnit.SECONDS);

新的 orTimeout 运算符与 Resilience4j TimeLimiter 相当。

如果您必须使用 Java8 并且想使用 Resilience4j,那么请执行

ThreadPoolBulkhead bulkhead = ThreadPoolBulkhead.ofDefaults("sample");
TimeLimiter timeLimiter = TimeLimiter.of(Duration.ofSeconds(1));

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(3);
CompletableFuture<String> future = timeLimiter
    .executeCompletionStage(scheduler, 
        bulkhead.decorateSupplier(() -> service.method())).toCompletableFuture();

TimeLimiter 允许使用您自己的 ScheduledExecutorService,而新的 orTimeout 运算符则不允许。

我建议阅读此博客 post -> http://iteratrlearning.com/java9/2016/09/13/java9-timeouts-completablefutures.html