Search code examples
javaresilience4j

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


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?


Solution

  • 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