Configuring Resilience4J Circuit Breakers
Starters
There are two starters for the Resilience4J implementations, one for reactive applications and one for non-reactive applications.
-
org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j
- non-reactive applications -
org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j
- reactive applications
Auto-Configuration
You can disable the Resilience4J auto-configuration by setting
spring.cloud.circuitbreaker.resilience4j.enabled
to false
.
Default Configuration
To provide a default configuration for all of your circuit breakers create a Customizer
bean that is passed a
Resilience4JCircuitBreakerFactory
or ReactiveResilience4JCircuitBreakerFactory
.
The configureDefault
method can be used to provide a default configuration.
@Bean
public Customizer<Resilience4JCircuitBreakerFactory> defaultCustomizer() {
return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
.timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(4)).build())
.circuitBreakerConfig(CircuitBreakerConfig.ofDefaults())
.build());
}
Reactive Example
@Bean
public Customizer<ReactiveResilience4JCircuitBreakerFactory> defaultCustomizer() {
return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
.circuitBreakerConfig(CircuitBreakerConfig.ofDefaults())
.timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(4)).build()).build());
}
Customizing The ExecutorService
If you would like to configure the ExecutorService
which executes the circuit breaker you can do so using the Resilience4JCircuitBreakerFactory
.
For example if you would like to use a context aware ExecutorService
you could do the following.
@Bean
public Customizer<ReactiveResilience4JCircuitBreakerFactory> defaultCustomizer() {
return factory -> {
ContextAwareScheduledThreadPoolExecutor executor = ContextAwareScheduledThreadPoolExecutor.newScheduledThreadPool().corePoolSize(5)
.build();
factory.configureExecutorService(executor);
};
}
Specific Circuit Breaker Configuration
Similarly to providing a default configuration, you can create a Customizer
bean this is passed a
Resilience4JCircuitBreakerFactory
or ReactiveResilience4JCircuitBreakerFactory
.
@Bean
public Customizer<Resilience4JCircuitBreakerFactory> slowCustomizer() {
return factory -> factory.configure(builder -> builder.circuitBreakerConfig(CircuitBreakerConfig.ofDefaults())
.timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(2)).build()), "slow");
}
In addition to configuring the circuit breaker that is created you can also customize the circuit breaker after it has been created but before it is returned to the caller.
To do this you can use the addCircuitBreakerCustomizer
method.
This can be useful for adding event handlers to Resilience4J circuit breakers.
@Bean
public Customizer<Resilience4JCircuitBreakerFactory> slowCustomizer() {
return factory -> factory.addCircuitBreakerCustomizer(circuitBreaker -> circuitBreaker.getEventPublisher()
.onError(normalFluxErrorConsumer).onSuccess(normalFluxSuccessConsumer), "normalflux");
}
Reactive Example
@Bean
public Customizer<ReactiveResilience4JCircuitBreakerFactory> slowCustomizer() {
return factory -> {
factory.configure(builder -> builder
.timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(2)).build())
.circuitBreakerConfig(CircuitBreakerConfig.ofDefaults()), "slow", "slowflux");
factory.addCircuitBreakerCustomizer(circuitBreaker -> circuitBreaker.getEventPublisher()
.onError(normalFluxErrorConsumer).onSuccess(normalFluxSuccessConsumer), "normalflux");
};
}
Circuit Breaker Properties Configuration
You can configure CircuitBreaker
and TimeLimiter
configs or instances in your application’s configuration properties file.
Property configuration has higher priority than Java Customizer
configuration.
Descending priority from top to bottom.
-
Method(id) config - on specific method or operation
-
Service(group) config - on specific application service or operations
-
Global default config
ReactiveResilience4JCircuitBreakerFactory.create(String id, String groupName)
Resilience4JCircuitBreakerFactory.create(String id, String groupName)
Global Default Properties Configuration
resilience4j.circuitbreaker:
configs:
default:
registerHealthIndicator: true
slidingWindowSize: 50
resilience4j.timelimiter:
configs:
default:
timeoutDuration: 5s
cancelRunningFuture: true
Configs Properties Configuration
resilience4j.circuitbreaker:
configs:
groupA:
registerHealthIndicator: true
slidingWindowSize: 200
resilience4j.timelimiter:
configs:
groupC:
timeoutDuration: 3s
cancelRunningFuture: true
Instances Properties Configuration
resilience4j.circuitbreaker:
instances:
backendA:
registerHealthIndicator: true
slidingWindowSize: 100
backendB:
registerHealthIndicator: true
slidingWindowSize: 10
permittedNumberOfCallsInHalfOpenState: 3
slidingWindowType: TIME_BASED
recordFailurePredicate: io.github.robwin.exception.RecordFailurePredicate
resilience4j.timelimiter:
instances:
backendA:
timeoutDuration: 2s
cancelRunningFuture: true
backendB:
timeoutDuration: 1s
cancelRunningFuture: false
-
ReactiveResilience4JCircuitBreakerFactory.create("backendA")
orResilience4JCircuitBreakerFactory.create("backendA")
will applyinstances backendA properties
-
ReactiveResilience4JCircuitBreakerFactory.create("backendA", "groupA")
orResilience4JCircuitBreakerFactory.create("backendA", "groupA")
will applyinstances backendA properties
-
ReactiveResilience4JCircuitBreakerFactory.create("backendC")
orResilience4JCircuitBreakerFactory.create("backendC")
will applyglobal default properties
-
ReactiveResilience4JCircuitBreakerFactory.create("backendC", "groupC")
orResilience4JCircuitBreakerFactory.create("backendC", "groupC")
will applyglobal default CircuitBreaker properties and config groupC TimeLimiter properties
For more information on Resilience4j property configuration, see Resilience4J Spring Boot 2 Configuration.
Bulkhead pattern supporting
If resilience4j-bulkhead
is on the classpath, Spring Cloud CircuitBreaker will wrap all methods with a Resilience4j Bulkhead.
You can disable the Resilience4j Bulkhead by setting spring.cloud.circuitbreaker.bulkhead.resilience4j.enabled
to false
.
Spring Cloud CircuitBreaker Resilience4j provides two implementation of bulkhead pattern:
-
a
SemaphoreBulkhead
which uses Semaphores -
a
FixedThreadPoolBulkhead
which uses a bounded queue and a fixed thread pool.
By default, Spring Cloud CircuitBreaker Resilience4j uses FixedThreadPoolBulkhead
. To modify the default behavior to use SemaphoreBulkhead
set the property spring.cloud.circuitbreaker.resilience4j.enableSemaphoreDefaultBulkhead
to true
.
For more information on implementation of Bulkhead patterns see the Resilience4j Bulkhead.
The Customizer<Resilience4jBulkheadProvider>
can be used to provide a default Bulkhead
and ThreadPoolBulkhead
configuration.
@Bean
public Customizer<Resilience4jBulkheadProvider> defaultBulkheadCustomizer() {
return provider -> provider.configureDefault(id -> new Resilience4jBulkheadConfigurationBuilder()
.bulkheadConfig(BulkheadConfig.custom().maxConcurrentCalls(4).build())
.threadPoolBulkheadConfig(ThreadPoolBulkheadConfig.custom().coreThreadPoolSize(1).maxThreadPoolSize(1).build())
.build()
);
}
Specific Bulkhead Configuration
Similarly to proving a default 'Bulkhead' or 'ThreadPoolBulkhead' configuration, you can create a Customizer
bean this
is passed a Resilience4jBulkheadProvider
.
@Bean
public Customizer<Resilience4jBulkheadProvider> slowBulkheadProviderCustomizer() {
return provider -> provider.configure(builder -> builder
.bulkheadConfig(BulkheadConfig.custom().maxConcurrentCalls(1).build())
.threadPoolBulkheadConfig(ThreadPoolBulkheadConfig.ofDefaults()), "slowBulkhead");
}
In addition to configuring the Bulkhead that is created you can also customize the bulkhead and thread pool bulkhead after they
have been created but before they are returned to caller. To do this you can use the addBulkheadCustomizer
and addThreadPoolBulkheadCustomizer
methods.
Bulkhead Example
@Bean
public Customizer<Resilience4jBulkheadProvider> customizer() {
return provider -> provider.addBulkheadCustomizer(bulkhead -> bulkhead.getEventPublisher()
.onCallRejected(slowRejectedConsumer)
.onCallFinished(slowFinishedConsumer), "slowBulkhead");
}
Thread Pool Bulkhead Example
@Bean
public Customizer<Resilience4jBulkheadProvider> slowThreadPoolBulkheadCustomizer() {
return provider -> provider.addThreadPoolBulkheadCustomizer(threadPoolBulkhead -> threadPoolBulkhead.getEventPublisher()
.onCallRejected(slowThreadPoolRejectedConsumer)
.onCallFinished(slowThreadPoolFinishedConsumer), "slowThreadPoolBulkhead");
}
Bulkhead Properties Configuration
You can configure ThreadPoolBulkhead and SemaphoreBulkhead instances in your application’s configuration properties file.
Property configuration has higher priority than Java Customizer
configuration.
resilience4j.thread-pool-bulkhead:
instances:
backendA:
maxThreadPoolSize: 1
coreThreadPoolSize: 1
resilience4j.bulkhead:
instances:
backendB:
maxConcurrentCalls: 10
For more inforamtion on the Resilience4j property configuration, see Resilience4J Spring Boot 2 Configuration.
Collecting Metrics
Spring Cloud Circuit Breaker Resilience4j includes auto-configuration to setup metrics collection as long as the right
dependencies are on the classpath. To enable metric collection you must include org.springframework.boot:spring-boot-starter-actuator
, and io.github.resilience4j:resilience4j-micrometer
. For more information on the metrics that
get produced when these dependencies are present, see the Resilience4j documentation.
You don’t have to include micrometer-core directly as it is brought in by spring-boot-starter-actuator
|