This document will show you how to use Resilience4j in Vert.x applications.
Resilience4j is a popular library that implements common fault tolerance strategies:
-
bulkhead (concurrency limiter)
-
circuit breaker
-
rate limiter
-
retry
-
time limiter (timeout)
In this how-to, we only demonstrate the usage of a circuit breaker, but the repository of this how-to contains Vert.x adapters for all strategies mentioned above.
Warning
|
Resilience4j 2.0, which we’ll use here, requires Java 17. |
You will use a circuit breaker with an HTTP client to prevent executing requests against a server that keeps returning errors. This serves two main purposes:
-
avoid generating more load on a server that may be overloaded,
-
failing fast when failure is very likely to occur anyway.
The application consists of a few classes:
-
the
CircuitBreakerVerticle
class -
the
VertxCircuitBreaker
adapter, which is included in the repository of this how-to
The code of this project contains Maven and Gradle build files that are functionally equivalent.
First, your pom.xml
file should declare version properties:
Next, import the Resilience4j and Vert.x BOMs to manage dependency versions:
Then, add a dependency on the Resilience4j circuit breaker library:
Finally, add dependencies on the Vert.x Web and Vert.x Web Client libraries:
The dependencies
block in your build.gradle.kts
file (assuming you use Gradle with the Kotlin DSL) should first import the Resilience4j and Vert.x BOMs to manage dependency versions:
Then, add a dependency on the Resilience4j circuit breaker library:
Finally, add dependencies on the Vert.x Web and Vert.x Web Client libraries:
First, let’s create the main CircuitBreakerVerticle
class:
This class will use the VertxCircuitBreaker
class, which is provided in the repository of this how-to.
In the start
method of the verticle, let’s create a single circuit breaker instance that will be shared among all requests.
For demonstration purposes, we will configure the circuit breaker to start calculating the failure rate after mere 5 requests:
Tip
|
The default settings make a lot more sense for a real-world application than our demonstration configuration. |
Next, we’ll use Vert.x Web to expose a simple endpoint. The sole purpose of that endpoint will be to perform an HTTP request and guard it with the circuit breaker:
This deserves some explanation.
The endpoint on /
uses the VertxCircuitBreaker
adapter that glues together the Resilience4j API and Vert.x Future
s.
The adapter expects a Supplier<Future>
as an action to be guarded.
The Future
here comes from the Vert.x Web Client get(8080, "localhost", "/does-not-exist")
call.
As you can imagine, the request we make here will never succeed.
Therefore, the circuit breaker will kick in after 5 requests (as configured above) and will prevent further calls to the guarded action.
Instead, the Future
returned by executeFuture
will fail instantly with the CallNotPermittedException
exception.
Finally, we’ll start the server:
The entire start
method of the verticle looks like this:
The CircuitBreakerVerticle
also needs a main
method:
Then you can run the application:
-
straight from your IDE, or
-
with Maven:
mvn clean compile exec:java
, or -
with Gradle:
./gradlew run
(Linux, macOS) orgradlew run
(Windows).
The following examples use the HTTPie command line HTTP client. Please refer to the installation documentation if you don’t have it installed on your system yet.
For the first 5 requests, the circuit breaker does not calculate the failure rate and will allow all actions to proceed. As expected, they will all fail:
http localhost:8080
http localhost:8080
http localhost:8080
http localhost:8080
http localhost:8080
You should see the following output 5 times:
Failed with: io.vertx.core.impl.NoStackTraceThrowable: Response status code 404 is not between 200 and 300
http localhost:8080
The 6th request will fail with a different message:
Failed with: io.github.resilience4j.circuitbreaker.CallNotPermittedException: CircuitBreaker 'my-circuit-breaker' is OPEN and does not permit further calls
We see that the circuit breaker prevented the execution of the request against the server.
This document covered:
-
creating an instance of the Resilience4j circuit breaker,
-
using the circuit breaker to guard an action whose result is a Vert.x
Future
.