Spring Cloud Circuit Breaker provides an abstraction across different circuit breaker implementations. It provides a consistent API to use in your applications allowing you the developer to choose the circuit breaker implementation that best fits your needs for your app.
Resilience4j is a lightweight fault tolerance library designed for Java 8+ functional programming. Provides several fault tolerance mechanisms: CircuitBreaker, Retry, RateLimiter, TimeLimiter, and Bulkhead.
In this post, I will cover common uses of Spring Cloud Circuit Breaker with Resilience4J. This post is based on Java 21, Spring Boot 3.5.3, and Spring Cloud 2025.0.0.
plugins { java id("org.springframework.boot") version "3.5.3" // Use the Spring Dependency Management plugin to manage Spring Cloud dependencies. id("io.spring.dependency-management") version "1.1.7" }
# Eureka client eureka: instance: preferIpAddress:true instanceId:${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}} client: registerWithEureka:true fetchRegistry:true serviceUrl: defaultZone:http://localhost:8761/eureka/ healthcheck: enabled:true server: # configure the service to use a random port number port:0
# resilience4j resilience4j.circuitbreaker: instances: circuit-breaker-resilience4j-2: registerHealthIndicator:true # the resilience4j configuration values are just for demostration slidingWindowSize:6 waitDurationInOpenState:10s failureRateThreshold:60
slidingWindowSize: Configures the size of the sliding window, which is used to record the outcome of calls when the CircuitBreaker is closed.
waitDurationInOpenState: The time that the CircuitBreaker should wait before transitioning from open to half-open.
failureRateThreshold: Configures the failure rate threshold in percentage. When the failure rate is equal to or greater than the threshold, the CircuitBreaker transitions to open and starts short-circuiting calls.
When the sliding window is full and the failure rate is equal to or greater than failureRateThreshold, the CircuitBreaker transitions to open.
@GetMapping("/callServiceWithCircuitBreaker") public String callServiceWithCircuitBreaker() { StringserviceId="my-eureka-client"; StringserviceUrl= discoveryClient.getInstances(serviceId).get(0).getUri().toString(); Supplier<String> supplier = () -> restTemplate.getForObject(serviceUrl + "/errorForTesting", String.class); Function<Throwable, String> fallbackFunction = throwable -> { if (throwable instanceof CallNotPermittedException) { return"Circuit breaker is open, request cannot be processed."; } else { System.out.println("Error making request to service. " + throwable.getMessage()); // Fallback: Sets alternative paths for failing requests return"This is a fallback message. Caused by " + throwable.getClass().getSimpleName() + ": " + throwable.getMessage(); } }; // It must be the same as the circuit breaker ID defined in the application.yml resilience4j.circuitbreaker.instances.{instanceId} Stringresilience4jCircuitBreakerId="my-circuit-breaker-resilience4j"; // Circuit breaker: Stops making requests when an invoked service is failing CircuitBreakercircuitBreaker= circuitBreakerFactory.create(resilience4jCircuitBreakerId); Stringresponse= circuitBreaker.run(supplier, fallbackFunction); System.out.println(response); return response; } }
4. Start and Verification
1. Starting a Eureka server and a Eureka client. And write a /errorForTesting API in the Eureka client. For using Eureka, you can refer to A Guide to Spring Cloud Netflix Eureka.
The APIs in the Eureka Client
@Value("${spring.application.name}") private String applicationName; @GetMapping("/greeting") public String greeting() { return"Hello from " + applicationName + " at " + newDate(); }
@GetMapping("/errorForTesting") public String errorForTesting() { // This endpoint is intentionally left to throw an error for testing purposes thrownewRuntimeException("This is a test error for circuit breaker demonstration."); }
2. Running the main() method in the SpringCloudCircuitBreakerApplication to start this Spring Cloud Circuit Breaker application.
3. Request the /callServiceWithCircuitBreaker endpoint to see the result.
According to the preceding resilience4j configuration in application.yml, if the number of requests is greater than 6 and the failure rate is equal to or greater than 60%, the Circuit Breaker will be open.
References
[1] Spring Microservices in Action, Second Edition