As multiple independent services interact with one another in a microservices design, maintaining system resilience becomes important. Managing failures that could arise from a service outage or high latency is one typical problem. A design pattern called the circuit breaker pattern solves this problem by offering a fallback and preventing a cascading failure. In this blog, we’ll look at the Circuit Breaker pattern of Spring Boot apps.
Understanding the Circuit Breaker Pattern:
An electrical circuit breaker and the circuit breaker pattern play a similar role. It keeps an eye out for malfunctions and, when reaching a predetermined threshold, opens the circuit to stop more calls to the malfunctioning service. This enables the system to fail gracefully and restart when the malfunctioning service is back up and running.
Spring Boot Implementation:
Maven
<!-- Add Resilience4j dependency in pom.xml -->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
</dependency>
Gradle
<!-- Add Resilience4j dependency in build.gradle -->
dependencies {
implementation 'io.github.resilience4j:resilience4j-spring-boot2:1.7.1'
}
Let’s now build a basic Spring Boot application that breaks circuits using Resilience4j.
1. Create a Spring Boot Application:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class CircuitBreakerTestApplication {
public static void main(String[] args) {
SpringApplication.run(CircuitBreakerTestApplication.class, args);
}
}
2. Create a Service with Circuit Breaker:
Create and name the service class as TestService, which will have a method that we want to protect with a circuit breaker:
import org.springframework.stereotype.Service;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
@Service
public class TestService {
@CircuitBreaker(name = "testService", fallbackMethod = "fallbackMethod")
public String invokeExternalService() {
// Here you can simulate a call to an external service
// In a real-world scenario, this could be an HTTP call, database query, etc.
if (Math.random() > 0.5) {
throw new RuntimeException("Service failure");
}
return "External service response";
}
public String fallbackMethod(Exception e) {
return "Fallback response";
}
}
In the CircuitBreaker annotation, name is the identifier for the circuit breaker, and fallbackMethod is the method that is to be called when the circuit is open.
3. Write a controller class to Invoke the TestService:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@Autowired
private TestService testService;
@GetMapping("/invokeService")
public String invokeService() {
return testService.invokeExternalService();
}
}
4. Enable Resilience4j Configuration
You can add the below properties to your application.properties or application.yml file to configure Resilience4j:
resilience4j.circuitbreaker.configs.default.failureRateThreshold=50
resilience4j.circuitbreaker.configs.default.slidingWindowSize=5
5: Monitor Circuit Breaker State (Not a must)
In order to monitor the state of the circuit breaker, you can also add the following dependencies for Micrometer and Prometheus:
Maven:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
Gradle:
implementation 'io.micrometer:micrometer-registry-prometheus'
Now Resilience4j Circuit Breaker dashboard can be accessed at http://localhost:8080/actuator/circuitbreakers.
6: Test Circuit Breaker
Utilize the /api/invokeService endpoint to submit requests while running your Spring Boot application. Change the Math.random() condition in the callExternalService method to simulate failures.
Observe how the state of the circuit breaker dashboard varies according to the success or failure of service calls.
Conclusion
The above example shows how to set up Resilience4j’s Circuit Breaker in a Spring Boot application in a basic manner. Depending on your unique use case and the interactions with external services, adjustments can be made as required.
References
https://spring.io/projects/spring-cloud-circuitbreaker
https://www.baeldung.com/spring-cloud-circuit-breaker
Github
https://github.com/tharindu1998/springboot-circuitbraker-example
Top comments (0)