Resilience4j: Getting Started with Circuit Breaker

black transistor beside capacitor
Reading Time: 4 minutes

Introduction

Resilience4j is a lightweight, easy-to-use fault tolerance library for Java 8 and functional programming. The Circuit Breaker is one of the main features provided by Resilience4j. It is used to stop cascading failures in a distributed system and provide fallback options.

To get started with Circuit Breaker in Resilience4j, you will need to add the resilience4j-circuit breaker dependency to your project. Once the dependency is added, you can create a CircuitBreaker instance and use it to decorate a function or method that you want to protect.

Why use Circuit Breaker?

Despite making investments to build a robust infrastructure, many IT organizations perpetuate dealing with database, hardware, and software downtime incidents at some point. Circuit breakers sanction the system to handle a few of these failures gracefully. It avails in averting cascading losses in an intricate distributed system and enables resilience in systems where failure is ineluctably foreordained by enabling fail expeditious and expeditious instauration.

There are many open-source libraries open for integrating the circuit breaker :

  • Resilience4j
  • Netflix Hystrix
  • Sentinel by Alibaba
  • Failsafe
  • Service Mesh like Istio, Linkerd, Cilium, etc.

How does the circuit breaker operate?

The circuit breaker pulls a function call inside the object of the circuit breaker, constantly monitoring the breakdowns.

When the failure reaches the threshold, the circuit breaker will trip and all other calls to the circuit breaker will return with an error, without the wrapped function being called.

The circuit breaker, at any given time, maybe in any of the following states:

CLOSED– It will be in the closed state and if the failures exceed the configured cut-off value at any time, the circuit will trip and move toward an open state.

OPEN – It will be open when failures are saved and the threshold is reached, meaning calls will begin to fail quickly without performing function calls.

HALF_OPEN – Breaker does not perform enveloped function calls when OPEN. After the waiting time has elapsed, it performs a status transition from OPEN to HALF_OPEN and allows only a configurable number of calls. Additional calls are dismissed until all authorized calls are completed. If the failure or slow call rate is higher than or equal to the configured threshold, the status becomes OPEN again. If the failure and slow call rates are below the threshold, the status will move to CLOSED.

Why Resilience4j?

The most popular framework that takes care of resilience is Hystrix, and unfortunately, Hystrix is in maintenance mode. Resilience4j is an alternative, lightweight, fault-tolerant library inspired by Netflix Hystrix and designed for Java 8 and functional programming. It is built on top of Vavr, a functional language extension for Java 8 that has no other external library dependencies.

Resilience4j provides higher-order functions (decorators) to extend any functional interface, method reference, or lambda expression. More than one decorator can be stacked on each functional interface, lambda expression, or method reference. The advantage is that you have the possibility to select only the decorators you need.

Implementation

Resilience4j delivers assets for different build tools such as Maven and Gradle. In our case, we use Maven for implementation.

    <dependency>

            <groupId>io.github.resilience4j</groupId>

            <artifactId>resilience4j-circuitbreaker</artifactId>

            <version>${resilience4j.version}</version>

     </dependency>

In Java, we need to define a custom circuit breaker configuration as shown below:

CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
  
  .failureRateThresold(100)

  .slowCallRateThresold(100)

  .waitDurationInOpenState(Duration.ofMillis(1000))

  .slowCallDurationThreshold(Duration.ofSeconds(3))

  .permittedNumberOfCallsInHalfOpenState(4))

  .minimumNumberOfCalls(10)

  .slidingWindowType(SlidingwindowType.TIME_BASED)

  .slideingWindowSize(5)

  .recordExceptions(IOException.class, TimeoutException.class)

  .build();

A circuit breaker registry can be created using the custom global configuration as shown in the figure :

CircuitBreakerregistry cktBreakerRegistry = 

                CircuitBreakerregistry.of(circuitBreakerConfig);

Decoration of a protected function to be controlled by a circuit breaker can be done as follows:

final Optional<CircuitBreaker> circuitBreaker =
 
 CircuitBreakerHttpClientFactory
               .getCircuitBreakerInstance(CircuitBreakerGatewayAdapterFactory.getAdapterService(className),cktBreakerRegistry);

if(circuitBreaker.isPresent()) {
   
    final Supplier<T> supplier = CircuitBreaker.decorateSupplier(circuitBreaker.get(),
  
          () -> this.sendMessage(httpMethod, url, queryParams, headers, requestBody, responseClass));

    final Try<T> result = Try.ofSupplier(supplier);
    
    return result.get();

}

//This is used to develop HTTP calls for other microservices

return this.sendMessage(httpmethod, url, queryParams, headers, requestBody, responseClass); 

Resilience4j also supports a module for micrometers to monitor systems such as InfluxDB or Prometheus.

     <dependency>

            <groupId>io.micrometer</groupId>
            
            <artifactId>micrometer-registry-influx</artifactId>
           
            <version>${micrometer-registry-influx.version}</version>
    
     </dependency>

     <dependency>

            <groupId>io.github.resilience4j</groupId>

            <artifactId>resilience4j-micrometer</artifactId>

            <version>${resilience4j-micrometer.version}</version>

     </dependency>

The metrics dashboard can be configured based on data requirements. There are several features that it supports out of the box

  • State of the circuit breaker
  • Failure call rates
  • Slow call rates
  • Not permitted calls

Here is an example of how to create a CircuitBreaker instance and use it to decorate a function:

Once the circuit breaker is created and decorated, it will automatically track the success and failure rate of the protected function and open the circuit if the failure rate exceeds the specified threshold. When the circuit is open, the protected function will not be executed and the fallback function will be executed instead.

You can also use the CircuitBreaker instance to check the state of the circuit, and its metrics of it, for example, the number of failures, successes, and calls.

This is just a basic example, you can further customize the CircuitBreaker by configuring the wait duration before closing the circuit, and the ring buffer size, among other things.

Summary

In this blog, we have discussed how introducing the circuit breaker into the system can help ensure high service availability. We also briefly discussed how the circuit breaker pattern gracefully handles failures and slowdowns of key services and helps those services recover by reducing the load.

References

  1. https://resilience4j.readme.io/docs/circuitbreaker
  2. https://reflectoring.io/circuitbreaker-with-resilience4j/

Written by 

He is a Software Consultant at Knoldus Inc. He has done B.Tech from Dr. APJ Kalam Technical University Uttar-Pradesh. He is passionate about his work and having the knowledge of various programming languages like Java, C++, Python. But he is passionate about Java development and curious to learn Java Technologies. He is always impatient and enthusiastic to learn new things. He is good skills of Critical thinking and problem solving and always enjoy to help others. He likes to play outdoor games like Football, Volleyball, Hockey and Kabaddi. Apart from the technology he likes to read scriptures originating in ancient India like Veda,Upanishad,Geeta etc.

Leave a Reply