HomeGuidesChangelog
GuidesGitHubLog In
Guides

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: enabled: true instances: backendA: baseConfig: default backendB: registerHealthIndicator: true slidingWindowSize: 10 minimumNumberOfCalls: 10 permittedNumberOfCallsInHalfOpenState: 3 waitDurationInOpenState: PT5s failureRateThreshold: 50 eventConsumerBufferSize: 10 recordFailurePredicate: resilience4j.micronaut.demo.exception.RecordFailurePredicate configs: default: registerHealthIndicator: true slidingWindowSize: 10 minimumNumberOfCalls: 5 permittedNumberOfCallsInHalfOpenState: 3 automaticTransitionFromOpenToHalfOpenEnabled: true waitDurationInOpenState: PT5s failureRateThreshold: 50 eventConsumerBufferSize: 10 recordExceptions: - io.micronaut.http.exceptions.HttpStatusException - java.util.concurrent.TimeoutException - java.io.IOException ignoreExceptions: - resilience4j.micronaut.demo.exception.BusinessException shared: slidingWindowSize: 100 permittedNumberOfCallsInHalfOpenState: 30 waitDurationInOpenState: PT1s failureRateThreshold: 50 eventConsumerBufferSize: 10 ignoreExceptions: - resilience4j.micronaut.demo.exception.BusinessException retry: enabled: true configs: default: maxAttempts: 3 waitDuration: 100 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: enabled: true configs: default: maxConcurrentCalls: 100 instances: backendA: maxConcurrentCalls: 10 backendB: maxWaitDuration: PT0.01S maxConcurrentCalls: 20 thread-pool-bulkhead: enabled: true configs: default: maxThreadPoolSize: 4 coreThreadPoolSize: 2 queueCapacity: 2 instances: backendA: baseConfig: default backendB: maxThreadPoolSize: 1 coreThreadPoolSize: 1 queueCapacity: 1 ratelimiter: enabled: true configs: default: registerHealthIndicator: false limitForPeriod: 10 limitRefreshPeriod: 1s timeoutDuration: 0 eventConsumerBufferSize: 100 instances: backendA: baseConfig: default backendB: limitForPeriod: 6 limitRefreshPeriod: PT0.5S timeoutDuration: 3s timelimiter: enabled: true configs: default: cancelRunningFuture: false 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: enabled: true configs: default: eventConsumerBufferSize: 10 failureRateThreshold: 60 permittedNumberOfCallsInHalfOpenState: 10 registerHealthIndicator: true slidingWindowSize: 100 waitDurationInOpenState: 10000 someShared: permittedNumberOfCallsInHalfOpenState: 10 slidingWindowSize: 50 instances: backendA: baseConfig: default waitDurationInOpenState: 5000 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:

@Bean @CircuitBreakerQualifier 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 TypeInstance Customizer classQualifier
Circuit breakerCircuitBreakerConfigCustomizer@CircuitBreakerQualifier
RetryRetryConfigCustomizer@RetryQualifier
Rate limiterRateLimiterConfigCustomizer@RateLimiterQualifier
BulkheadBulkheadConfigCustomizer@BulkheadQualifier
ThreadPoolBulkheadThreadPoolBulkheadConfigCustomizer@ThreadPoolBulkheadQualifier
Time LimiterTimeLimiterConfigCustomizer@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:

@Bulkhead(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

@Override @Bulkhead(name = BACKEND_A, type = Bulkhead.Type.THREADPOOL) @TimeLimiter(name = BACKEND_A) @CircuitBreaker(name = BACKEND_A, fallbackMethod = "futureFallback") public CompletableFuture<String> futureTimeout() { Try.run(() -> Thread.sleep(5000)); return CompletableFuture.completedFuture("Hello World from backend A"); } @Executable public String fallback() { return "Recovered HttpServerErrorException"; } @Executable 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.