Getting Started
Getting started with resilience4j-micronaut
Setup
Add the Micronaut Starter of Resilience4j to your compile dependency.
include the maven bom for micronaut dependencies io.micronaut:micronaut-bom:2.0.0.M3
.
repositories {
mavenCentral()
jCenter()
}
dependencyManagement {
imports {
mavenBom 'io.micronaut:micronaut-bom:2.0.0.M3'
}
}
dependencies {
annotationProcessor "io.micronaut:micronaut-inject-java"
annotationProcessor "io.micronaut:micronaut-validation"
compile "io.github.resilience4j:resilience4j-micronaut:${resilience4jVersion}"
}
Demo
Setup and usage in Micronaut is demonstrated into a demo.
Configuration
You can configure your CircuitBreaker, Retry, RateLimiter, Bulkhead, Thread pool bulkhead and TimeLimiter instances in Micronaut’s application.yml
config file.
For example
resilience4j
circuitbreaker
enabledtrue
instances
backendA
baseConfig default
backendB
registerHealthIndicatortrue
slidingWindowSize10
minimumNumberOfCalls10
permittedNumberOfCallsInHalfOpenState3
waitDurationInOpenState PT5s
failureRateThreshold50
eventConsumerBufferSize10
recordFailurePredicate resilience4j.micronaut.demo.exception.RecordFailurePredicate
configs
default
registerHealthIndicatortrue
slidingWindowSize10
minimumNumberOfCalls5
permittedNumberOfCallsInHalfOpenState3
automaticTransitionFromOpenToHalfOpenEnabledtrue
waitDurationInOpenState PT5s
failureRateThreshold50
eventConsumerBufferSize10
recordExceptions
io.micronaut.http.exceptions.HttpStatusException
java.util.concurrent.TimeoutException
java.io.IOException
ignoreExceptions
resilience4j.micronaut.demo.exception.BusinessException
shared
slidingWindowSize100
permittedNumberOfCallsInHalfOpenState30
waitDurationInOpenState PT1s
failureRateThreshold50
eventConsumerBufferSize10
ignoreExceptions
resilience4j.micronaut.demo.exception.BusinessException
retry
enabledtrue
configs
default
maxAttempts3
waitDuration100
retryExceptions
io.micronaut.http.exceptions.HttpStatusException
java.util.concurrent.TimeoutException
java.io.IOException
ignoreExceptions
resilience4j.micronaut.demo.exception.BusinessException
instances
backendA
baseConfig default
backendB
baseConfig default
bulkhead
enabledtrue
configs
default
maxConcurrentCalls100
instances
backendA
maxConcurrentCalls10
backendB
maxWaitDuration PT0.01S
maxConcurrentCalls20
thread-pool-bulkhead
enabledtrue
configs
default
maxThreadPoolSize4
coreThreadPoolSize2
queueCapacity2
instances
backendA
baseConfig default
backendB
maxThreadPoolSize1
coreThreadPoolSize1
queueCapacity1
ratelimiter
enabledtrue
configs
default
registerHealthIndicatorfalse
limitForPeriod10
limitRefreshPeriod 1s
timeoutDuration0
eventConsumerBufferSize100
instances
backendA
baseConfig default
backendB
limitForPeriod6
limitRefreshPeriod PT0.5S
timeoutDuration 3s
timelimiter
enabledtrue
configs
default
cancelRunningFuturefalse
timeoutDuration PT2s
instances
backendA
baseConfig default
backendB
baseConfig default
You can also override the default configuration, define shared configurations and overwrite them in Micronaut’s application.yml
config file.
For example:
resilience4j
circuitbreaker
enabledtrue
configs
default
eventConsumerBufferSize10
failureRateThreshold60
permittedNumberOfCallsInHalfOpenState10
registerHealthIndicatortrue
slidingWindowSize100
waitDurationInOpenState10000
someShared
permittedNumberOfCallsInHalfOpenState10
slidingWindowSize50
instances
backendA
baseConfig default
waitDurationInOpenState5000
backendB
baseConfig someShared
You can also override the configuration of a specific CircuitBreaker, Bulkhead, Retry, RateLimiter or TimeLimiter instances by using Customizer for specific instance names. The following shows an example of how to override a configured CircuitBreaker backendA in the above in the YAML file:
public CircuitBreakerConfigCustomizer testCustomizer() {
return CircuitBreakerConfigCustomizer
.of("backendA", builder -> builder.slidingWindowSize(100));
}
Resilience4j has its own customizer types which can be used as shown above. The beans have to be marked with the correct Qualifier:
Resilienc4j Type | Instance Customizer class | Qualifier |
---|---|---|
Circuit breaker | CircuitBreakerConfigCustomizer | @CircuitBreakerQualifier |
Retry | RetryConfigCustomizer | @RetryQualifier |
Rate limiter | RateLimiterConfigCustomizer | @RateLimiterQualifier |
Bulkhead | BulkheadConfigCustomizer | @BulkheadQualifier |
ThreadPoolBulkhead | ThreadPoolBulkheadConfigCustomizer | @ThreadPoolBulkheadQualifier |
Time Limiter | TimeLimiterConfigCustomizer | @TimeLimiterQualifier |
Configuration through Interceptor
beans can be intercepted before they are injected. so additional customization can be issued through intercepting the Resilience4j properties.
package io.micronaut.ignite.docs.config;
@Singleton
public class BulkheadConfiguration implements BeanCreatedEventListener<BulkheadProperties> {
@Override
public IgniteConfiguration onCreated(BeanCreatedEvent<BulkheadConfigurationProperties> event) {
CircuitBreakerProperties configuration = event.getBean();
return configuration;
}
}
Resilience4j Type |
---|
BulkheadConfigurationProperties |
CircuitBreakerConfigurationProperties |
RateLimiterProperties |
RetryProperties |
TimeLimiterProperties |
ThreadPoolBulkheadProperties |
Annotations
The Micronaut starter provides annotations and AOP Aspects which are auto-configured.
RateLimiter, Retry, CircuitBreaker and Bulkhead annotations support synchronous return types and asynchronous types like CompletableFuture and reactive types like Spring Reactor's Flux and Mono (if you imported appropriate package like resilience4j-reactor
).
Bulkhead annotation has a type attribute to define which bulkhead implementation will be used. By default it is semaphore but you can switch to thread pool by setting the type attribute in the annotation:
name = BACKEND_A, type = Bulkhead.Type.THREADPOOL)
public CompletableFuture<String> futureFailure() {
CompletableFuture<String> future = new CompletableFuture<>();
future.completeExceptionally(new IOException("BAM!"));
return future;
}
(
An example of all resilience4j supported spring aspects
name = BACKEND_A, type = Bulkhead.Type.THREADPOOL)
(name = BACKEND_A)
(name = BACKEND_A, fallbackMethod = "futureFallback")
public CompletableFuture<String> futureTimeout() {
Try.run(() -> Thread.sleep(5000));
return CompletableFuture.completedFuture("Hello World from backend A");
}
public String fallback() {
return "Recovered HttpServerErrorException";
}
public CompletableFuture<String> futureFallback() {
return CompletableFuture.completedFuture("Recovered specific TimeoutException");
}
(
It's important to remember that a fallback method should be placed in the same class and must be marked with @Executable.
The fallback method has to have the same matching argument signature and the same matching return type.
Aspect order
The Resilience4j Aspects order is following: Retry ( CircuitBreaker ( RateLimiter ( TimeLimiter ( Bulkhead ( Function ) ) ) ) )
There is currently no way to change the order of the executing aspects.
Updated almost 4 years ago