Spring Boot - Circuit Breaker Pattern with Resilience4J
Last Updated :
30 Aug, 2024
The Circuit Breaker pattern is essential in microservices architecture to prevent cascading failures. When a service fails repeatedly due to network issues, unavailability, or other reasons, the Circuit Breaker opens to prevent additional requests from hitting the failing service. This approach helps maintain the system's overall health and provides fallback mechanisms for graceful degradation.
Resilience4J is a lightweight fault tolerance library, taking inspiration from Netflix Hystrix, but it is uniquely designed for modern Java applications, with strong support for functional programming It supports various resilience patterns, including Circuit Breaker, Rate Limiter, Bulkhead, and Retry.
Circuit Breaker with Resilience4J
The Circuit Breaker pattern is key to building resilient microservices. It acts as a fail-safe mechanism that prevents repeated failures in service calls by "breaking the circuit" and stopping the flow of requests when a service becomes unresponsive or fails consistently. This approach allows the system to fail fast and recover gracefully.
How the Circuit Breaker Works
- Closed State: The circuit is closed and allows requests to pass through. If failures occur and reach the threshold, the circuit opens.
- Open State: No requests can pass through. After a timeout, the circuit transitions to the half-open state.
- Half-Open State: A restricted number of requests are allowed to pass through. If they succeed, the circuit returns to the closed state; if they fail, it returns to the open state.
Resilience4J's Circuit Breaker monitors calls to the downstream service, tracks failure rates, and trips the circuit if the failure rate crosses the defined threshold.
Why Use the Circuit Breaker Pattern?
- Prevents Cascading Failures: Isolates failures to prevent a chain reaction that could bring down multiple services.
- Graceful Degradation: Provides fallback responses to ensure a better user experience when failures occur.
- Improves System Stability: Prevents continuous attempts to execute failing operations, thus improving overall stability.
How Resilience4J Implements the Circuit Breaker
Resilience4J provides a comprehensive and flexible way to implement the Circuit Breaker pattern in Spring Boot applications. It monitors downstream service calls and automatically trips the circuit if the failure rate exceeds the defined threshold. By using annotations like @CircuitBreaker
and defining properties in the application.properties
or application.yml
file, developers can control the behavior of the Circuit Breaker.
Configuration Parameters in Resilience4J
- failureRateThreshold: Sets the failure rate threshold percentage. When the failure rate meets or exceeds this percentage, the circuit transitions to the open state.
- slidingWindowSize: Defines the size of the sliding window used for calculating the failure rate. It can be count-based or time-based.
- minimumNumberOfCalls: Specifies the minimum number of calls needed before the Circuit Breaker begins calculating the failure rate. The Circuit Breaker will not open until this number is reached.
- waitDurationInOpenState: Duration the Circuit Breaker stays in the open state before transitioning to the half-open state.
- permittedNumberOfCallsInHalfOpenState: Number of test calls allowed in the half-open state to determine if the Circuit Breaker should close again.
Implementing the Circuit Breaker Pattern with Resilience4J in Spring Boot
In this example, we’ll create a simple Spring Boot application to demonstrate the use of the Circuit Breaker pattern using Resilience4J. We’ll configure the Circuit Breaker to handle failures gracefully and provide fallback responses when the service fails.
Step 1: Create a New Spring Boot Project
Create a new Spring Boot project using IntelliJ IDEA with the following options:
- Name: spring-boot-circuit-breaker
- Language: Java
- Type: Maven
- Packaging: Jar
Click on the Next button.
Step 2: Add Dependencies
Add the following dependencies into the Spring Boot project.
- Spring Web
- Resilience4J
- Spring Boot DevTools
- Lombok
Click on the Create button.
Project Structure
The file structure should look like this:
Step 3: Configure Application Properties
Rename application.properties
to application.yml
and add the following configuration:
resilience4j:
circuitbreaker:
instances:
sampleService:
registerHealthIndicator: true
slidingWindowSize: 5
minimumNumberOfCalls: 5
failureRateThreshold: 50
waitDurationInOpenState: 10s
permittedNumberOfCallsInHalfOpenState: 3
eventConsumerBufferSize: 10
management:
endpoints:
web:
exposure:
include: '*'
Step 4: Create the SampleService Class
Create the SampleService class to simulate the external service call that might fails of the Spring Boot application.
SampleService.java
Java
package com.gfg.springbootcircuitbreaker;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import org.springframework.stereotype.Service;
/**
* Service class to simulate external service calls that might fail.
*/
@Service
public class SampleService {
private static final String SAMPLE_SERVICE = "sampleService";
/**
* Simulates a service call that might fail.
* @return Response from the external service or throws an exception
*/
@CircuitBreaker(name = SAMPLE_SERVICE, fallbackMethod = "fallbackResponse")
public String callExternalService() {
// Simulating a random failure
if (Math.random() > 0.5) {
throw new RuntimeException("Service failed");
}
return "Service call succeeded";
}
/**
* Fallback method called when the circuit breaker is open.
* @param ex Exception thrown
* @return Fallback response
*/
public String fallbackResponse(Exception ex) {
return "Fallback response: " + ex.getMessage();
}
}
Explaination:
- @CircuitBreaker(name = SAMPLE_SERVICE, fallbackMethod = "fallbackResponse"): This annotation marks the callExternalService method to be protected by the circuit breaker named as the SampleService. If this method failes due to the exception then it will call the fallbackResponse method.
- fallbackResponse(Exception ex): This method can be defined as the fallback, which is called when the circuit breaker is open. It can provides the simple fallback response to indicate the failure gracefully.
Step 5: Create the CircuitBreakerController Class
Create the CircuitBreakerController class to define the REST endpoints for the testing the circuit breaker of the Spring Boot application.
CircuitBreakerController.java
Java
package com.gfg.springbootcircuitbreaker;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Controller class to define REST endpoints for testing the Circuit Breaker.
*/
@RestController
public class CircuitBreakerController {
private final SampleService sampleService;
public CircuitBreakerController(SampleService sampleService) {
this.sampleService = sampleService;
}
/**
* Endpoint to test the Circuit Breaker.
* @return Response from SampleService
*/
@GetMapping("/test")
public String testCircuitBreaker() {
return sampleService.callExternalService();
}
}
@RestController
: Defines a RESTful controller.@GetMapping("/test")
: Endpoint for testing the Circuit Breaker functionality.
Step 6: Main Class
This is the entry point of the application. There is no changes are required in the main class.
Java
package com.gfg.springbootcircuitbreaker;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Main class to run the Spring Boot application.
*/
@SpringBootApplication
public class SpringBootCircuitBreakerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootCircuitBreakerApplication.class, args);
}
}
pom.xml file:
XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.gfg</groupId>
<artifactId>spring-boot-circuit-breaker</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-circuit-breaker</name>
<description>spring-boot-circuit-breaker</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2023.0.3</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
spring-boot-starter-web
: Provides web application support.resilience4j-spring-boot2
: Integrates Resilience4J with Spring Boot.spring-boot-starter-actuator
: Provides production-ready features like monitoring and management.lombok
: Simplifies boilerplate code.
Step 7: Run the Application
To run the application, execute the following command:
mvn spring-boot:run
Output:
Step 8: Testing the Application
Use Postman or any REST client to test the /test
endpoint:
GET http://localhost:8080/test
- On a successful service call, you should receive "Service call succeeded".
- If the service fails, you should see the fallback response "Fallback response: Service failed".
Application Logs
In the application logs, it will show the exception of the Spring Boot application.
Conclusion
In this article, we demonstrated how to implement the Circuit Breaker pattern using Resilience4J in a Spring Boot application. We configured the Circuit Breaker in the application.yml
file, implemented a service with a Circuit Breaker, and tested the functionality through a REST endpoint. This approach helps build resilient applications by managing failures effectively and providing fallback mechanisms.
Similar Reads
Implementing a Basic Circuit Breaker with Hystrix in Spring Boot Microservices
The Circuit breaker is a design pattern used in software development to improve system resilience by preventing cascading failures. It monitors failures and opens the circuit when a certain threshold is reached, preventing further calls to the failing service. This prevents the system from being ove
4 min read
Spring Boot - RestTemplateBuilder with Example
Before jumping into RestTemplateBuilder let's have a quick overview of RestTemplate. RestTemplate is a synchronous REST client which performs HTTP requests using a simple template-style API. We can also state that RestTemplate class is a synchronous client and is designed to call REST services. Rest
12 min read
Spring Boot â Setting Up a Spring Boot Project with Gradle
Spring Boot is a Java framework designed to simplify the development of stand-alone, production-ready Spring applications with minimal setup and configuration. It simplifies the setup and development of new Spring applications, reducing boilerplate code.In this article, we will guide you through set
4 min read
Spring Security Integration with Spring Boot
Spring Security is a powerful and customizable authentication and access control framework for Java applications. It provides comprehensive security services for Java EE-based enterprise software applications. This article will integrate Spring Security with a Spring Boot application, covering confi
5 min read
What is Circuit Breaker Pattern in Microservices?
The Circuit Breaker pattern is a design pattern used in microservices to enhance system resilience and fault tolerance. It acts like an electrical circuit breaker by preventing an application from repeatedly trying to execute an operation that is likely to fail, which can lead to cascading failures
10 min read
Spring Boot - Configure a RestTemplate with RestTemplateBuilder
RestTemplate is a synchronous REST client which performs HTTP requests using a simple template-style API. We can also state that RestTemplate class is a synchronous client and is designed to call REST services. RestTemplateBuilder is a Builder that can be used to configure and create a RestTemplate.
12 min read
A Guide to RestClient in Spring Boot
In Spring Boot applications, external services often need to be communicated via REST APIs. Traditionally, RestTemplate was used for this purpose, but it is now considered a legacy approach. Starting from Spring Framework 6.1 and Spring Boot 3.2, RestClient has been introduced as a modern alternativ
9 min read
Circuit Breaker with Bulkhead Isolation in Microservices
In modern software architecture, particularly in distributed systems, ensuring resilience and fault tolerance is crucial. Microservices have become a popular architectural style that allows for the development of scalable applications. Two essential patterns in this context are Circuit Breakers and
10 min read
Difference Between Fuse And Circuit Breaker
The main difference between fuse and circuit breaker is that in case of fuse the wire of the fuse melts in case of overflow of current while in case of circuit breaker the trip coil gets energized and thus moves away. Understanding the difference between fuses and circuit breakers is essential for e
5 min read
Rate Limter vs. Circuit Breaker in Microservices
Microservices architecture brings scalability, flexibility, and resilience to modern applications. However, these benefits also come with their own set of challenges, particularly in managing the interactions between services. To ensure system reliability and performance, two crucial patterns often
5 min read