I have a web application running in a Tomcat server that performs calls to an external server.
Now, I want to use Resilience4j's TimeLimiter
to retrict the waiting time for the response and additionally a Bulkhead
to limit the amount of parallel calls to the external server.
I don't need asynchronous calls to the external system as the Tomcat thread has to wait for the response or timeout, anyway.
What would be the best way to combine the TimeLimiter
and the Bulkhead
in this scenario? Do I need a SemaphoreBulkhead
or the ThreadPoolBulkhead
and how would I wrap my external system call in a Future
that is needed for the TimeLimiter
?
you can't combine a SemaphoreBulkhead and a TimeLimiter, since the TimeLimiter cannot stop the execution of a task if it is running the same Thread.
Therefore you can only combine a TimeLimiter and a ThreadPoolBulkhead. But it only makes sense if you want to have a non-blocking/async code and not block your Thread.
If you want blocking code, you could just use:
CompletableFuture.supplyAsync(() -> service.method()).get(1, TimeUnit.SECONDS);
If you want non-blocking code and you can use Java9 or greater, you can just do:
CompletableFuture.supplyAsync(() -> service.method()).orTimeout(1, TimeUnit.SECONDS);
The new orTimeout
operator is comparable to Resilience4j TimeLimiter.
If you have to use Java8 and want to use Resilience4j, then do
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();
The TimeLimiter allows to use your own ScheduledExecutorService, whereas the new orTimeout
operator does not.
I suggest to read this blog post -> http://iteratrlearning.com/java9/2016/09/13/java9-timeouts-completablefutures.html