We are calling few downstreams from our service, and we need to provide the circuit breaker, retry, timelimiter and bulkhead feature to all the downstream services call.
Current code-base:
@Override
@Bulkhead(name = "downstream1", type = Type.THREADPOOL, fallbackMethod = "downstream1Fallback")
@TimeLimiter(name = "downstream1", fallbackMethod = "downstream1Fallback")
@CircuitBreaker(name = "downstream1", fallbackMethod = "downstream1Fallback")
@Retry(name = "downstream1", fallbackMethod = "downstream1Fallback")
public CompletableFuture<String> downstream1(String a) {
return CompletableFuture.completedFuture(process(a)));
}
public CompletableFuture<String> downstream1Fallback(String a,
Exception e) {
return CompletableFuture.completedFuture(""); // empty string.
}
app.properties :
# timeouts
resilience4j.timelimiter.instances. downstream1.timeout-duration=30 #30 ms
# retry
resilience4j.retry.instances.downstream1.max-attempts=1
# bulkhead
resilience4j.thread-pool-bulkhead.instances.downstream1.core-thread-pool-size=30
resilience4j.thread-pool-bulkhead.instances.downstream1.max-thread-pool-size=50
resilience4j.thread-pool-bulkhead.instances.downstream1.queue-capacity=10
Use-case :
If the thread-pool by Bulkhead is full OR there's a timeout from downstream OR circuit-is-open, I don't want to do the retrying in all of these scenarios, and retry in every other scenario.
Retry should only happen if there's an server exception from the downstream.
As per the official docs : https://resilience4j.readme.io/docs/getting-started-3#aspect-order. This is the order.
Retry ( CircuitBreaker ( RateLimiter ( TimeLimiter ( Bulkhead ( Function
My understanding from docs :
case 1: If thread-pool is full, fallback will be called with
exception type BulkheadFullException.class - no retry
: else new thread will be spawned to call downstream.
case 3: If spawned thread takes more time than what's set on
"resilience4j.timelimiter", fallback will be called with
exception type TimeoutException.class - no retry
case 4: If circuit is open, fallback will be called with
exception type CallNotPermittedException.class - no retry.
case 5: If thread-pool is not full and no timeout and circuit is
closed as well, and we got some other exception than
the above mentioned exceptions, than only retry to downstream
call will trigger using config values set on "resilience4j.retry".
Is this flow understanding correct, about how resilience4j would work OR do I need to change/add any config in the app.properties file, to serve the use-case described above.
you could either define exceptions on which you want to retry using
retryExceptionsor define exceptions you wish to ignore usingignoreExceptionsIf either of the solutions does not work for you then you can have a predicateretryOnResultPredicatewhich evaluates if a result should be retried. The Predicate must return true if the result should be retried, otherwise, it must return false.like below.
and configure this predicate in retry properties as