Mastering Spring Cloud Circuit Breakers with Resilience4J, Sentinel, and Spring Retry
This guide explains how Spring Cloud abstracts multiple circuit‑breaker implementations, shows synchronous and reactive usage with code examples, and demonstrates custom configuration of Resilience4J circuit breakers for Java backend applications.
Introduction
Spring Cloud Circuit Breaker abstracts various circuit‑breaker implementations (Resilience4J, Sentinel, Spring Retry) and offers a uniform API so developers can pick the most suitable one.
Supported Implementations
Resilience4J
Sentinel
Spring Retry
Synchronous (blocking) usage
When the CircuitBreakerFactory starter is on the classpath, a bean implementing this API is auto‑configured. Add the appropriate Maven dependency:
<code><dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
</code>Or for reactive applications:
<code><dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
</dependency>
</code>Example of a simple service using RestTemplate and CircuitBreakerFactory :
<code>@Service
public static class UsersService {
private RestTemplate rest;
private CircuitBreakerFactory cbFactory;
public UsersService(RestTemplate rest, CircuitBreakerFactory cbFactory) {
this.rest = rest;
this.cbFactory = cbFactory;
}
public Users getUser() {
// "remoteUser" is the circuit‑breaker identifier
return cbFactory.create("remoteUser")
.run(() -> rest.getForObject("/100", Users.class),
throwable -> "用户用户信息失败");
}
}
</code>The CircuitBreakerFactory.create method returns a CircuitBreaker instance. Its run method accepts a Supplier (the protected code) and a Function (fallback) that receives the Throwable causing the circuit to open. The fallback is optional.
Reactive usage
If Project Reactor is present, you can use ReactiveCircuitBreakerFactory :
<code>@Service
public static class DemoControllerService {
private ReactiveCircuitBreakerFactory cbFactory;
private WebClient webClient;
public DemoControllerService(WebClient webClient, ReactiveCircuitBreakerFactory cbFactory) {
this.webClient = webClient;
this.cbFactory = cbFactory;
}
public Mono<Users> getUser() {
return webClient.get()
.uri("/100")
.retrieve()
.bodyToMono(Users.class)
.transform(it -> cbFactory.create("remoteUser")
.run(it, throwable -> Mono.just("获取用户失败")));
}
}
</code>The ReactiveCircuitBreakerFactory.create creates a ReactiveCircuitBreaker . Its run method wraps a Mono or Flux and optionally a fallback function that receives the triggering Throwable .
Configuration
Customize the circuit‑breaker factory by defining a bean that implements Customizer<Resilience4JCircuitBreakerFactory> :
<code>@Component
public class PackCircuitBreakerCustomizer implements Customizer<Resilience4JCircuitBreakerFactory> {
@Override
public void customize(Resilience4JCircuitBreakerFactory tocustomize) {
tocustomize.configure(builder -> {
// timeout configuration
builder.timeLimiterConfig(
TimeLimiterConfig.custom()
.timeoutDuration(Duration.ofMillis(3000))
.build()
);
// circuit‑breaker configuration
builder.circuitBreakerConfig(
CircuitBreakerConfig.custom()
.failureRateThreshold(0.1f) // open when failure rate ≥ threshold
.minimumNumberOfCalls(3) // at least 3 calls before evaluating
.build()
);
}, "a1", "a2", "a3", "remoteUser"); // apply to these IDs only
// default configuration for all other circuit‑breakers
tocustomize.configureDefault(id ->
new Resilience4JConfigBuilder(id)
.circuitBreakerConfig(CircuitBreakerConfig.ofDefaults())
.timeLimiterConfig(TimeLimiterConfig.ofDefaults())
.build()
);
}
}
</code>For detailed customization of each implementation, refer to the official documentation:
Resilience4J: Link
Sentinel: Link
Spring Retry: Link
Some implementations, such as Resilience4JCircuitBreaker , invoke custom methods on each CircuitBreaker#run call, which may be inefficient. In such cases you can use CircuitBreaker#once instead.
Example of registering a one‑time listener:
<code>Customizer.once(circuitBreaker -> {
circuitBreaker.getEventPublisher()
.onStateTransition(event -> log.info("{}: {}", event.getCircuitBreakerName(), event.getStateTransition()));
}, CircuitBreaker::getName);
</code>End of tutorial.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.