Resilience4J Circuit Breaker

Article created on Dec 2019

This article demonstrates on how to implement circuit breaker using Resilience4J. Circuit Breaker is a design pattern used to provide client resiliency. Client resiliency protects client that uses a remote service from failure when there is an exception thrown from the remote service, and propagates to client side. Circuit breaker prevents client keeps invoke on failure service.

Resilience4J Circuit breaker provides resiliency by decorating the invoke source using functional programming style. Invoke source is one or more code statements that invoke the remote service. Circuit breaker pattern consists of three states: CLOSE, OPEN, and HALF-OPEN.

(1) In CLOSE state, circuit breaker allows invoke-source to invoke the remote service.

(2) During CLOSE state, circuit breaker records the statistic of success and failure rate of invoke. If statistic shows that there are too many failures in invoke, or response is too slow from the remote service, the circuit breaker will transit to OPEN state.

(3) In OPEN state, circuit breaker blocks the execution of invoking source, and throws CallNotPermittedException.

(4) After a timed duration has elapsed, circuit breaker transits to HALF-OPEN state. At this state, circuit breaker restricts the number of executions of invoke source.

(5) Similar to CLOSE state, circuit breaker records the statistic of success and failure of invoke during the HALF-OPEN state. If statistic shows that there are too many failures in invoke, or response is too slow from the remote service, the circuit breaker will transit back to OPEN state. Else, circuit breaker transits back to CLOSE state.

Circuit Breaker Configuration

The application requires some configuration before the circuit breaker can be used. This configuration is provided in Spring configuration class. In this article, is the Java class for this purpose:

@Configuration
public class MicroserviceConfig {
@Bean("DataServiceCb")
public CircuitBreaker circuitBreaker() {
CircuitBreakerConfig circuitBreakerConfig =
CircuitBreakerConfig.custom()
.slidingWindowSize(4)
.minimumNumberOfCalls(2)
.slidingWindowType(SlidingWindowType.COUNT_BASED)
.failureRateThreshold(50)
.waitDurationInOpenState(Duration.ofSeconds(60))
.permittedNumberOfCallsInHalfOpenState(3)
.build();

CircuitBreaker circuitBreaker =
(CircuitBreakerStateMachine)
CircuitBreaker.of("DataServiceCb", circuitBreakerConfig);

return circuitBreaker;
}
}

is the API for configuring the circuit breaker.

minimumNumberOfCalls: The minimum number of method calls/invokes that are required for the circuit breaker to start failure rate calculation. This parameter value is increased by one when the invoke source is invoked, regardless whether the invoke results in an exception or return with no exception.

slidingWindowType: Either count based or time in seconds based. In this article, count based sliding window is used.

slidingWindowSize: Provides the number of size of sliding window.

failureRateThreshold: Provides the threshold of failure rate in percentage.

waitDurationInOpenState: The duration for the circuit breaker to stay in OPEN state after circuit breaker transits from CLOSE to OPEN state.

permittedNumberOfCallsInHalfOpenState: The number of invoke/method calls to invoke source that is permitted when the circuit breaker is in HALF-OPEN state.

method is used to create the instance of circuit breaker. The first parameter is the name for the circuit breaker, and the second parameter is the circuit breaker configuration.

Failure rate formula

In count based sliding window, the failure rate formula is the number of failures invoke / total number of invoking x 100%. The total number of invoke is the number of failures invoke + number of successes invoke.

The circuit breaker will start the failure rate calculation when the total number of invoke equals to parameter. When the failure rate is equal or greater than the failureRateThreshold parameter, the Circuit Breaker transits from the CLOSE state of OPEN state.

When a circuit breaker collects the metrics, the total number of invoke never exceed the parameter. For example, suppose the is four, and the number of success invoke is also four. If there is fifth success invokes, a circuit breaker will not increase the number of success invoke by one, but stops at the number that is provided in parameter. If the fifth invoke is a failure invoke, then circuit breaker will decrease the number of success invoke by one, and increases the number of failures invoke by one. Therefore, circuit breaker always keeps the total number of invoke equals to .

Circuit Breaker in action

Try to execute the source code provided in this article, uses a web browser and sends a request to this URL: to test the circuit breaker.

There is no result in browser screen, but in the SpringToolSuite/Eclipse console. With the URL, the console will show this:

testresult: data 
Circuit Breaker Statistic:
--------------------------
State: CLOSED
Failure rate: -1.0
Failure invoke count: 0
Success invoke count: 1
CallNotPermitted count: 0
--------------------------

is a RESTFul service created in RestfulService.java:

@RestController
public class RestfulService {
@Autowired private CircuitBreaker circuitBreaker;

@GetMapping("/test")
public void test(@RequestParam(required=false) String simulatedError) {
String error = simulatedError == null ? "":simulatedError;

try {
Supplier<String> sup=()->{
if(error.equals("1"))
throw new IllegalStateException();

return "data";
};

String test = CircuitBreaker
.decorateSupplier(
circuitBreaker, sup
)
.get();


System.out.println("testresult: "+test);
}
catch(IllegalStateException excp) {
System.out.println("IllegalStateException");
}
catch(CallNotPermittedException excp) {
System.out.println("CallNotPermittedException");
}

showStatistic();
}

private void showStatistic() {
Metrics met = circuitBreaker.getMetrics();

System.out.println("Circuit Breaker Statistic:");
System.out.println("--------------------------");
System.out.println("State: "+
circuitBreaker.getState());
System.out.println("Failure rate: "+
met.getFailureRate());
System.out.println("Failure invoke count: "+
met.getNumberOfFailedCalls());
System.out.println("Success invoke count: "+
met.getNumberOfSuccessfulCalls());
System.out.println("CallNotPermitted count: "+
met.getNumberOfNotPermittedCalls());
System.out.println("--------------------------");
}
}

creates a Supplier. This supplier is used to simulate the remote service. The supplier simply returns a string value “data”. When the parameter has a value of 1, then the supplier will simulate a service error by throwing the :

             Supplier<String> sup=()->{
if(error.equals("1"))
throw new IllegalStateException();

return "data";
};

Therefore, When the supplier returns successfully, the circuit breaker will increase the number of success invoke. If supplier throws IllegalStateException, then circuit breaker will increase the number of failure invoke. In order for circuit breaker to record the number of success and failure invoke, the circuit breaker must decorate the supplier:

             
System.out.println("testresult: "+test);
}
catch(IllegalStateException excp) {
System.out.println("IllegalStateException");
}
catch(CallNotPermittedException excp) {
System.out.println("CallNotPermittedException");
}
showStatistic();

method is invoked to execute the supplier. The restful service, then prints the value of the variable on screen. If the restful service catches the , then the console will show a string value of ”IllegalStateException”, or ”CallNotPermittedException” when is caught. After all, the restful service invokes method to show the metric data that is collected by the circute breaker. Therefore, when the is firstly executed, the state is in CLOSE state. When the application is just started, executes the with . Then executes another request with . Observed that the statistic shows that the circuit breaker transits to OPEN state because the failure rate reaches 50% of failure threshold.

IllegalStateException 
Circuit Breaker Statistic:
--------------------------
State: OPEN
Failure rate: 50.0
Failure invoke count: 1
Success invoke count: 1
CallNotPermitted count: 0
--------------------------

The circuit breaker will stay in OPEN state for 60 seconds, according to parameter. Any invoke during that 60 seconds, circuit breaker will throw .

CallNotPermittedException 
Circuit Breaker Statistic:
--------------------------
State: OPEN
Failure rate: 100.0
Failure invoke count: 2
Success invoke count: 0
CallNotPermitted count: 1
--------------------------

After the 60 seconds have elapsed, the circuit breaker transits to HALF-OPEN state. When in HALF-OPEN state, the circuit breaker will permit the invoke but limited to the number specified in parameter.

IllegalStateException 
Circuit Breaker Statistic:
--------------------------
State: HALF_OPEN
Failure rate: -1.0
Failure invoke count: 1
Success invoke count: 0
CallNotPermitted count: 0
--------------------------

The Circuit breaker will also start the statistic collection in HALF-OPEN state. If the failure rate equals to or more than , the circuit breaker transits back to OPEN state. If the number of success invoke equals to the parameter and the failure rate is less than the , the state transits back to CLOSE state.

Type of Threshold

In this article, the application configures circuit breaker for . The is calculated based on the number of success and failure invoke. Besides the failureRateThreshold, there is another type of threshold, which is . The is calculated based on the number of invoke that is slow in performance. The will increase the number of the slow call by one when the invoke’s execution time is equals or more than 60 seconds. The 60 seconds is the default behavior for the circuit breaker. However, this article uses a simulated supplier which has no performance problem, so the is never reaching its threshold. When develop the application for production project, the design of circuit breaker must take both and into accounts.

Source code

Github: SpringBootR4jCircuitBreaker.zip
Development environment: Java11, Spring Tool Suite 4, SpringBoot2.1.8, Resilience4J 1.2.0

I am very interested in Java, web app and mobile app development. I enjoy doing R&D in Java during my spare time

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store