Backend Development 7 min read

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.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Mastering Spring Cloud Circuit Breakers with Resilience4J, Sentinel, and Spring Retry

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>&lt;dependency&gt;
  &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
  &lt;artifactId&gt;spring-cloud-starter-circuitbreaker-resilience4j&lt;/artifactId&gt;
&lt;/dependency&gt;
</code>

Or for reactive applications:

<code>&lt;dependency&gt;
  &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
  &lt;artifactId&gt;spring-cloud-starter-circuitbreaker-reactor-resilience4j&lt;/artifactId&gt;
&lt;/dependency&gt;
</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&lt;Resilience4JCircuitBreakerFactory&gt; :

<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.

Javabackend developmentSpring Cloudcircuit breakerResilience4j
Spring Full-Stack Practical Cases
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.