<resilience4j.version>2.1.0</resilience4j.version>
<vertx.version>5.0.0.CR2</vertx.version>
在 Vert.x 中使用 Resilience4j
本文档将向您展示如何在 Vert.x 应用程序中使用 Resilience4j。
Resilience4j 是一个流行的库,它实现了常见的容错策略
-
舱壁(并发限制器)
-
断路器
-
速率限制器
-
重试
-
时间限制器(超时)
在本操作指南中,我们只演示了断路器的用法,但本操作指南的仓库中包含了上述所有策略的 Vert.x 适配器。
我们在此将使用的 Resilience4j 2.0 需要 Java 17。 |
您将构建什么
您将把断路器与 HTTP 客户端一起使用,以防止对持续返回错误的服务器执行请求。这主要有两个目的:
-
避免对可能已过载的服务器产生更多负载,
-
当失败很可能发生时快速失败。
该应用程序由几个类组成:
-
CircuitBreakerVerticle
类 -
VertxCircuitBreaker
适配器,包含在本操作指南的仓库中
您需要什么
-
文本编辑器或 IDE
-
Java 17 或更高版本
-
Maven 或 Gradle
创建项目
此项目的代码包含功能等效的 Maven 和 Gradle 构建文件。
使用 Maven
首先,您的 pom.xml
文件应声明版本属性:
pom.xml
:版本属性接下来,导入 Resilience4j 和 Vert.x 的 BOM 以管理依赖版本:
pom.xml
:BOM 导入<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-bom</artifactId>
<version>${resilience4j.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-stack-depchain</artifactId>
<version>${vertx.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
然后,添加对 Resilience4j 断路器库的依赖:
pom.xml
:Resilience4j 依赖<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-circuitbreaker</artifactId>
</dependency>
最后,添加对 Vert.x Web 和 Vert.x Web 客户端库的依赖:
pom.xml
:Vert.x 依赖<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web-client</artifactId>
</dependency>
使用 Gradle
您的 build.gradle.kts
文件(假设您使用带有 Kotlin DSL 的 Gradle)中的 dependencies
块应首先导入 Resilience4j 和 Vert.x 的 BOM 以管理依赖版本:
build.gradle.kts
:BOM 导入implementation(platform("io.github.resilience4j:resilience4j-bom:2.1.0"))
implementation(platform("io.vertx:vertx-stack-depchain:5.0.0.CR2"))
然后,添加对 Resilience4j 断路器库的依赖:
build.gradle.kts
:Resilience4j 依赖implementation("io.github.resilience4j:resilience4j-circuitbreaker")
最后,添加对 Vert.x Web 和 Vert.x Web 客户端库的依赖:
build.gradle.kts
:Vert.x 依赖implementation("io.vertx:vertx-web")
implementation("io.vertx:vertx-web-client")
使用断路器保护 Vert.x Web 客户端请求
首先,让我们创建主 CircuitBreakerVerticle
类
CircuitBreakerVerticle
类public class CircuitBreakerVerticle extends VerticleBase {
}
该类将使用 VertxCircuitBreaker
类,该类在本操作指南的仓库中提供。
创建断路器
在 verticle 的 start
方法中,让我们创建一个断路器实例,该实例将在所有请求之间共享。出于演示目的,我们将断路器配置为在仅 5 个请求后开始计算失败率:
CircuitBreaker cb = CircuitBreaker.of("my-circuit-breaker", CircuitBreakerConfig.custom()
.minimumNumberOfCalls(5)
.build());
与我们的演示配置相比,默认设置对于实际应用程序更具意义。 |
创建服务器
接下来,我们将使用 Vert.x Web 暴露一个简单的端点。该端点的唯一目的是执行 HTTP 请求并使用断路器保护它:
Router router = Router.router(vertx);
WebClient client = WebClient.create(vertx);
router.get("/").handler(ctx -> {
VertxCircuitBreaker.executeFuture(cb, () -> {
return client.get(8080, "localhost", "/does-not-exist")
.as(BodyCodec.string())
.send()
.expecting(HttpResponseExpectation.SC_SUCCESS);
})
.onSuccess(response -> ctx.end("Got: " + response.body() + "\n"))
.onFailure(error -> ctx.end("Failed with: " + error.toString() + "\n"));
});
这需要一些解释。
/
上的端点使用了 VertxCircuitBreaker
适配器,它将 Resilience4j API 和 Vert.x Future
连接起来。该适配器期望一个 Supplier<Future>
作为要保护的操作。
这里的 Future
来自 Vert.x Web 客户端的 get(8080, "localhost", "/does-not-exist")
调用。
正如您所能想象的,我们在这里发出的请求永远不会成功。因此,断路器将在 5 个请求(如上配置)后介入,并阻止进一步调用受保护的操作。相反,executeFuture
返回的 Future
将立即因 CallNotPermittedException
异常而失败。
启动服务器
最后,我们将启动服务器:
return vertx.createHttpServer()
.requestHandler(router)
.listen(8080)
.onSuccess(server -> {
System.out.println("HTTP server started on port " + server.actualPort());
});
verticle 的整个 start
方法如下所示:
start
方法@Override
public Future<?> start() {
CircuitBreaker cb = CircuitBreaker.of("my-circuit-breaker", CircuitBreakerConfig.custom()
.minimumNumberOfCalls(5)
.build());
Router router = Router.router(vertx);
WebClient client = WebClient.create(vertx);
router.get("/").handler(ctx -> {
VertxCircuitBreaker.executeFuture(cb, () -> {
return client.get(8080, "localhost", "/does-not-exist")
.as(BodyCodec.string())
.send()
.expecting(HttpResponseExpectation.SC_SUCCESS);
})
.onSuccess(response -> ctx.end("Got: " + response.body() + "\n"))
.onFailure(error -> ctx.end("Failed with: " + error.toString() + "\n"));
});
return vertx.createHttpServer()
.requestHandler(router)
.listen(8080)
.onSuccess(server -> {
System.out.println("HTTP server started on port " + server.actualPort());
});
}
运行应用程序
CircuitBreakerVerticle
还需要一个 main
方法:
main
方法public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
vertx.deployVerticle(new CircuitBreakerVerticle());
}
然后您可以运行应用程序:
-
直接从您的 IDE 运行,或者
-
使用 Maven:
mvn clean compile exec:java
,或者 -
使用 Gradle:
./gradlew run
(Linux, macOS) 或gradlew run
(Windows)。
前 5 个请求
对于前 5 个请求,断路器不计算失败率,并将允许所有操作继续。正如预期,它们都将失败:
http localhost:8080
http localhost:8080
http localhost:8080
http localhost:8080
http localhost:8080
您应该看到以下输出 5 次:
Failed with: io.vertx.core.impl.NoStackTraceThrowable: Response status code 404 is not between 200 and 300
接下来,断路器介入
http localhost:8080
第 6 个请求将以不同的消息失败:
Failed with: io.github.resilience4j.circuitbreaker.CallNotPermittedException: CircuitBreaker 'my-circuit-breaker' is OPEN and does not permit further calls
我们看到断路器阻止了对服务器的请求执行。
总结
本文档涵盖了
-
创建 Resilience4j 断路器实例,
-
使用断路器保护其结果为 Vert.x
Future
的操作。