CircuitBreaker immediate fallback

Viewed 707

I followed https://resilience4j.readme.io/docs/getting-started-3 for Resilience4J documentation.

I have a problem, my circuitbreaker is immediately connecting to the fallback( on the first invoke) when the primary-backend is not available.

@Bean
public CircuitBreakerConfig circuitBreakerConfig() {
    return CircuitBreakerConfig.custom()
            .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.COUNT_BASED)
            .slidingWindowSize(5)
            .minimumNumberOfCalls(5)
            .failureRateThreshold(4)
            .build();
}

I also tried moving the config to application.yml, but still the same behavior.

import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;

@CircuitBreaker(name = "backendA", fallbackMethod = "fallbackA")
public String backendA() {
  return restTemplate.getForObject("http://localhost:9999/backendA", String.class);
}

public String fallbackA(Exception e) {
    return restTemplate.getForObject("http://localhost:8080/partner", String.class);
}

Can someone help?

//UPDATE

More details below. As shown in the code above, my app is making a call to /backendA, behind a circuit breaker. It is expected that as per config, if backendA is not available, the should fail 5 times and 6th call onwards fallback to /partner API. Or in other words, circuit should open after 5 calls.

This is how I tested.

I started the application. Both backendA and fallbackA are available. After a few calls, I killed backendA. the next call to backendA is falling back to /partner while I expect the next 5 calls to backendA fails without a fallback. Is my expectation correct?

2 Answers

After some research, I came to know that fallback on intermittent failures is an expected behaviour, though I could not find it documented anywhere. So even if the circuit is CLOSED, fallback will be invoked if the method throws a matching exception.

Note: If you are not happy with the immediate fallback, wrap it with a RETRY config.

@CircuitBreaker- you should expect the result that if it's status is open that you will immediately receive a fallback and it no longer calls your desired service.

If you expect the result that when you turn off your called backend service and you want 5 call until you get fallback you need use @Retry, if the call fails, then it will try to call your service again.

If you use multiple notations, you can read more about the order here

Related