V-Techhub: Implementing Circuit Breaker in Spring Boot with Resilience4j

In Vinova’s experience with microservices, where applications rely on a network of interdependent services, ensuring system reliability is key to a smooth-sailing project. But what happens when one of those services fails? How do you prevent a single point of failure from cascading and taking down your entire application?

Resilient and fault-tolerant systems depend on the Circuit Breaker design pattern, a robust solution designed to protect your system from cascading failures by temporarily halting requests to failing services. This January, V-Techub and Vinova’s top tech talent will take a deeper look at Circuit Breaker in Spring Boot with Resilience4j, specifically into the concept of Circuit Breaker design pattern and how to implement it in Spring Boot using Resilience4j.

  1. What is Circuit Breaker Design Pattern?

The Circuit Breaker Pattern is a widely used design pattern in distributed systems, designed to handle failures gracefully and maintain the stability of applications. It acts as a safety mechanism that prevents a cascading failure across multiple services by halting requests to a service that is experiencing issues—such as timeouts, service downtime, or errors.

When a service is identified as failing, the Circuit Breaker trips, preventing further requests from reaching the affected service. This not only avoids overloading the failing service but also ensures the overall system remains functional. By doing so, the pattern helps mitigate risks like system-wide outages or data inconsistencies caused by failed requests.

  1. Advantages of Circuit Beaker pattern

Using the Circuit Breaker Pattern in distributed systems provides numerous benefits that enhance reliability, performance, and fault tolerance. Here are the key advantages:

1. Prevents Cascading Failures

  • When a service encounters an issue, such as overload or unresponsiveness, the Circuit Breaker stops new requests from being sent to that service. This prevents the failure from propagating to other services.

2. Improves Reliability and Availability

  • Circuit Breakers ensure that other parts of the system continue to operate normally even if one or more services fail. This increases system uptime and provides a better user experience.

3. Reduces Load on Failing Services

  • Automatically cutting off requests to a failing service reduces the strain on it, allowing the service time to recover instead of being overwhelmed further.

4. Supports Fallback Logic

  • Circuit Breakers often integrate with fallback mechanisms, providing default data or alternative logic when a service is unavailable. 
  • End users are less impacted by service failures because the system can quickly respond with fallback data or temporary solutions instead of failing completely

5. Protects System Resources

  • By halting unnecessary requests to a failing service, Circuit Breaker conserves valuable resources like CPU, memory, and network connections.
  1. How Circuit Breaker Works

The Circuit Breaker operates in three primary states:

1. Closed:

  • This is the initial state of the Circuit Breaker.
  • When the system is functioning normally, the Circuit Breaker remains “Closed” and monitors the rate of failed requests over a defined period.
  • If the failure rate exceeds a predefined threshold, the Circuit Breaker transitions to the Open state. Otherwise, it continues processing requests as usual.

2. Open:

  • The Circuit Breaker transitions to “Open” when the failure rate surpasses the threshold.
  • In this state, all requests to the failing service are blocked. The Circuit Breaker can:
    • Throw an exception to allow for appropriate handling.
    • Execute a fallback function to perform alternative actions.
  • The time spent in the Open state is configurable. After this time expires, it transitions to Half-Open.

3. Half-Open:

  • In this state, the Circuit Breaker allows a limited number of requests to pass through to the service.
  • If the failure rate remains high, it transitions back to the Open state to block further requests.
  • If the failure rate falls below the threshold, the Circuit Breaker transitions back to the Closed state, indicating that the service has recovered.

Besides that, the Circuit Breaker also has two Additional states:

  • DISABLED: The Circuit Breaker is turned off, and all requests to the service are executed without restriction.
  • FORCE_OPEN: The Circuit Breaker remains permanently in the “Open” state, blocking all requests to the service.
  1. Implementing Circuit Breaker with Resilience4j

Resilience4j is a lightweight, easy-to-use fault tolerance library designed for Java applications. It provides robust implementations of various resilience patterns, including Circuit Breaker, Rate Limiter, Retry, and more. Resilience4j is built with functional programming in mind and works seamlessly with frameworks like Spring Boot.

By implementing the Circuit Breaker Pattern using Resilience4j, developers can:

  • Protect downstream services from being overwhelmed during failures.
  • Prevent unnecessary retries to failing services.
  • Maintain system stability by gracefully handling failures with fallbacks.
  1. Hands on

Scenario: Consider a simplified system facilitating online purchases, comprising two primary services: order-service and address-service.

During the purchase process, users may wish to review the order details before confirmation. In such cases, the “view order details” action triggers a request to order-service.

Order-service subsequently utilizes the postal code present in the order information to query address information from address-service.

Upon receiving the address information, order-service updates the order details and returns the updated information to the user.


The address-service will expose a simple API to return delivery addresses. The order-service will also expose an API to return order details. Notably, this API will call the address-service to retrieve delivery address information. For simplicity, a RestTemplate will be used for communication between the order-service and the address-service.

As you noticed, we’re annotating the method with “@CircuitBreaker”. The attribute “name” is assigned as “order-service” which means every configuration of “order-service” instance is applied for this method. (These configurations will reside in the application.properties or application.yaml file, as detailed later.)

Furthermore, there is an attribute called fallbackMethod, which serves as a backup method in case the call to the address-service fails. It’s crucial to note that the return types of the getOrderByPostCode method and the fallbackMethod must be identical. This is why, when implementing a method with a circuit breaker, it’s advisable to define the method’s return type using an interface (e.g., Type in this case) for easier handling.

The circuit breaker is configured in the application.yaml file. There’s a section: Circuit Breaker -> instances -> order-service. This order-service name matches the “name“ attribute of the method mentioned earlier. Therefore, any configurations under order-service in the YAML file will apply to the method with the name attribute set to order-service.

From the configuration, there are some important properties you should know:

sliding-window-type: The number of requests is recorded and aggregated in the last “sliding-window-size” seconds.

failure-rate-threshold: Trigger Circuit Breaker if at least “failure-rate-threshold” of requests have failed.

minimum-number-of-calls: Records at least “minimum-number-of-calls” requests in the last “sliding-window-size” seconds before calculating the failure rate.

automatic-transition-from-open-to-half-open-enabled: After ”wait-duration-in-open-state” seconds, Circuit Breaker will automatically transition from open to half-open state.

wait-duration-in-open-state: If triggered, wait at least “wait-duration-in-open-state” seconds before allowing more calls.

permitted-number-of-calls-in-half-open-state: After “wait-duration-in-open-state” time has passed, allow another “permitted-number-of-calls-in-half-open-state” requests and wait for them to calculate the failure rate again.

sliding-window-size: Record the result of the last “sliding-window-size” seconds.

That’s all for the configuration! Now in case address-service is not responding properly (service is down), we’ll get the response below. 

Conclusion

The Circuit Breaker Pattern is an essential tool for building resilient distributed systems. By implementing it with Resilience4j in Spring Boot, developers can ensure their applications are better equipped to handle failures gracefully. With its lightweight nature and seamless Spring Boot integration, Resilience4j simplifies the process of incorporating fault tolerance into your applications.

Start using Circuit Breakers today to make your systems more reliable and user-friendly!

Categories: Others
jaden: Jaden Mills is a tech and IT writer for Vinova, with 8 years of experience in the field under his belt. Specializing in trend analyses and case studies, he has a knack for translating the latest IT and tech developments into easy-to-understand articles. His writing helps readers keep pace with the ever-evolving digital landscape. Globally and regionally. Contact our awesome writer for anything at jaden@vinova.com.sg !