resilience4j

Resilience4j is a fault tolerance library for Java™

Resilience4j is a lightweight fault tolerance library inspired by Netflix Hystrix, but designed for functional programming.
Resilience4j provides higher-order functions (decorators) to enhance any functional interface, lambda expression or method reference with a Circuit Breaker, Rate Limiter, Retry or Bulkhead. You can stack more than one decorator on any functional interface, lambda expression or method reference. The advantage is that you have the choice to select the decorators you need and nothing else.

Supplier<String> supplier = () -> service.sayHelloWorld(param1);

String result = Decorators.ofSupplier(supplier)
  .withBulkhead(Bulkhead.ofDefaults("name"))
  .withCircuitBreaker(CircuitBreaker.ofDefaults("name"))
  .withRetry(Retry.ofDefaults("name"))
  .withFallback(asList(CallNotPermittedException.class, BulkheadFullException.class),  
      throwable -> "Hello from fallback")
  .get()

With Resilience4j you don’t have to go all-in, you can pick what you need.

Get Started

Feign

A Java to HTTP client binder inspired by Retrofit, JAXRS-2.0, and WebSocket. https://github.com/OpenFeign/feign

Resilience4j decorators for Feign. Similar to https://github.com/OpenFeign/feign/tree/master/hystrix[HystrixFeign], resilience4j-feign makes it easy to incorporate "fault tolerance" patterns into the feign framework, such as the CircuitBreaker and RateLimiter.

Current Features

  • CircuitBreaker
  • RateLimiter
  • Fallback

Decorating Feign Interfaces

The Resilience4jFeign.builder is the main class for creating fault tolerance instances of feign.
It extends the Feign.builder and can be configured in the same way with the exception of adding a custom InvocationHandlerFactory. Resilience4jFeign uses its own InvocationHandlerFactory to apply the decorators. Decorators can be built using the FeignDecorators class. Multiple decorators can be combined.
The following example shows how to decorate a feign interface with a RateLimiter and CircuitBreaker:

public interface MyService {
            @RequestLine("GET /greeting")
            String getGreeting();
            
            @RequestLine("POST /greeting")
            String createGreeting();
        }

        CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("backendName");
        RateLimiter rateLimiter = RateLimiter.ofDefaults("backendName");
        FeignDecorators decorators = FeignDecorators.builder()
                                         .withRateLimiter(rateLimiter)
                                         .withCircuitBreaker(circuitBreaker)
                                         .build();
        MyService myService = Resilience4jFeign.builder(decorators).target(MyService.class, "http://localhost:8080/");

Calling any method of the MyService instance will invoke a CircuitBreaker and then a RateLimiter.
If one of these mechanisms take affect, then the corresponding RuntimeException will be thrown, for example, CircuitBreakerOpenException or RequestNotPermitted (Hint: These do not extend the FeignException class).

The following diagram illustrates how the decorators are stacked.

Ordering of Decorators

The order in which decorators are applied correspond to the order in which they are declared.
When building FeignDecorators, it is important to be wary of this, since the order affects the resulting behavior.

FeignDecorators decoratorsA = FeignDecorators.builder()
                                         .withCircuitBreaker(circuitBreaker)
                                         .withRateLimiter(rateLimiter)
                                         .build();
                                         
        FeignDecorators decoratorsB = FeignDecorators.builder()
                                         .withRateLimiter(rateLimiter)
                                         .withCircuitBreaker(circuitBreaker)
                                         .build();

With decoratorsA the RateLimiter will be called before the CircuitBreaker. That means that even if the CircuitBreaker is open, the RateLimiter will still limit the rate of calls. decoratorsB applies the reverse order. Meaning that once the CircuitBreaker is open, the RateLimiter will no longer be in affect.

Fallback

Fallbacks can be defined that are called when Exceptions are thrown. Exceptions can occur when the HTTP request fails, but also when one of the FeignDecorators activates, for example, the CircuitBreaker.

public interface MyService {
            @RequestLine("GET /greeting")
            String greeting();
        }

        MyService requestFailedFallback = () -> "fallback greeting";
        MyService circuitBreakerFallback = () -> "CircuitBreaker is open!";
        CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("backendName");
        FeignDecorators decorators = FeignDecorators.builder()
                                         .withFallback(requestFailedFallback, FeignException.class)
                                         .withFallback(circuitBreakerFallback, CircuitBreakerOpenException.class)
                                         .build();
        MyService myService = Resilience4jFeign.builder(decorators).target(MyService.class, "http://localhost:8080/", fallback);

In this example, the requestFailedFallback is called when a FeignException is thrown (usually when the HTTP request fails), whereas the circuitBreakerFallback is only called in the case of a CircuitBreakerOpenException. Check the FeignDecorators class for more ways to filter fallbacks.

All fallbacks must implement the same interface that is declared in the "target" (Resilience4jFeign.Builder#target) method, otherwise an IllegalArgumentException will be thrown.
Multiple fallbacks can be assigned to handle the same Exception with the next fallback being called when the previous one fails.

A fallback can consume a thrown Exception if needed. This can be useful if the fallback may have different behaviours depending on the Exception, or to simply log the Exception.
Be aware that such a fallback will be instantiated for every exceptions thrown.

public interface MyService {
            @RequestLine("GET /greeting")
            String greeting();
        }

        public class MyFallback implements MyService {
            private Exception cause;

            public MyFallback(Exception cause) {
                this.cause = cause;
            }

            public String greeting() {
                if (cause instanceOf FeignException) {
                    return "Feign Exception";
                } else {
                    return "Other exception";
                }
            }
        }

        FeignDecorators decorators = FeignDecorators.builder()
                .withFallbackFactory(MyFallback::new)
                .build();

Updated 4 months ago

Feign


A Java to HTTP client binder inspired by Retrofit, JAXRS-2.0, and WebSocket. https://github.com/OpenFeign/feign

Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.