编辑此页面

Quarkus Reactive 架构

Quarkus 是响应式的。甚至不止于此:Quarkus 统一了响应式和命令式编程。您甚至不必选择:您可以实现响应式组件和命令式组件,然后在同一应用程序中组合它们。无需使用不同的堆栈、工具或 API;Quarkus 连接了两个世界。

此页面将解释我们所说的响应式是什么,以及 Quarkus 如何启用它。我们还将讨论执行和编程模型。最后,我们将列出提供响应式方面的 Quarkus 扩展。

什么是响应式

响应式这个词被过度使用,并且与许多概念相关联,例如背压、Monad 或事件驱动架构。因此,让我们明确我们所说的响应式是什么。

响应式是一组构建响应式分布式系统和应用程序的原则和指南。《响应式宣言》将响应式系统描述为具有四个特征的分布式系统

  1. 响应迅速 - 它们必须及时响应

  2. 弹性 - 它们会根据波动的负载自行调整

  3. 韧性 - 它们可以优雅地处理故障

  4. 异步消息传递 - 响应式系统的组件使用消息进行交互

Reactive Systems Pillars

除此之外,《响应式原则白皮书》还列出了一组规则和模式,以帮助构建响应式系统。

响应式系统和 Quarkus

响应式系统是一种架构风格,可以概括为:正确完成的分布式系统。依赖异步消息传递有助于强制执行不同组件之间的松散耦合(在空间和时间方面)。您将消息发送到虚拟目的地。接收者可以位于任何位置,甚至可能在消息调度时尚未存在。弹性支柱允许根据负载扩大和缩小各个组件。弹性还提供冗余,这有助于提高韧性。失败是不可避免的。构成响应式系统的组件必须优雅地处理它们,避免级联故障,并自我适应。

响应式系统可以在面对故障和波动的负载下继续处理请求。Quarkus 已经为此量身定制。它提供的功能将帮助您设计、实施和运营响应式系统。

响应式应用程序

Quarkus 不仅会帮助您构建响应式系统。它还将确保每个组成部分都强制执行响应式原则并高效运行。

效率至关重要,尤其是在云和容器化环境中。CPU 和内存等资源在多个应用程序之间共享。消耗大量内存的贪婪应用程序效率低下,并会给同级应用程序带来惩罚。您可能需要请求更多的内存、CPU 或更大的虚拟机。这要么会增加您的每月云账单,要么会降低您的部署密度。

I/O 是几乎所有现代系统的重要组成部分。无论是调用远程服务、与数据库交互还是向 Broker 发送消息,这些都是基于 I/O 的操作。高效地处理它们对于避免贪婪应用程序至关重要。因此,Quarkus 使用非阻塞 I/O,这允许少量的 OS 线程管理许多并发 I/O。因此,Quarkus 应用程序允许更高的并发性,使用更少的内存,并提高部署密度。

Quarkus 如何启用响应式?

在底层,Quarkus 有一个响应式引擎。该引擎由 Eclipse Vert.x 和 Netty 提供支持,处理非阻塞 I/O 交互。

Quarkus Reactive Core

Quarkus 扩展和应用程序代码可以使用此引擎来编排 I/O 交互、与数据库交互、发送和接收消息等等。

响应式执行模型

虽然使用非阻塞 I/O 具有巨大的好处,但它并非免费。实际上,它引入了一种与经典框架使用的执行模型截然不同的新执行模型。

传统应用程序使用阻塞 I/O 和命令式(顺序)执行模型。因此,在公开 HTTP 端点的应用程序中,每个 HTTP 请求都与一个线程相关联。通常,该线程将处理整个请求,并且该线程在请求期间仅绑定到服务于该请求。当处理需要与远程服务交互时,它使用阻塞 I/O。线程被阻塞,等待 I/O 的结果。虽然该模型易于开发(因为一切都是顺序的),但它有一些缺点。要处理并发请求,您需要多个线程,因此您需要引入一个工作线程池。此池的大小限制了应用程序的并发性。此外,每个线程在内存和 CPU 方面都有成本。大型线程池会导致贪婪的应用程序。

Imperative Execution Model and Worker Threads

正如我们上面所看到的,非阻塞 I/O 避免了这个问题。几个线程可以处理许多并发 I/O。如果我们回到 HTTP 端点示例,请求处理将在其中一个 I/O 线程上执行。因为只有少数线程,所以您需要明智地使用它们。当请求处理需要调用远程服务时,您不能再阻塞线程。您可以调度 I/O 并传递一个延续,即 I/O 完成后要执行的代码。

Reactive Execution Model and I/O Threads

此模型效率更高,但我们需要一种编写代码来表达这些延续的方法。

响应式编程模型

Quarkus 架构基于非阻塞 I/O 和消息传递,允许支持多种响应式开发模型,这些模型在表达延续的方式上各不相同。使用 Quarkus 编写响应式代码的两种主要方法是

  • 使用 Mutiny 进行响应式编程,以及

  • 使用 Kotlin 进行协程

首先,Mutiny 是一个直观的、事件驱动的响应式编程库。使用 Mutiny,您可以编写事件驱动的代码。您的代码是一个接收事件并处理它们的管道。管道中的每个阶段都可以看作是一个延续,因为当管道的上游部分发出事件时,Mutiny 会调用它们。

Mutiny API 经过定制,可以提高代码库的可读性和可维护性。Mutiny 提供了编排异步操作所需的一切,包括并发执行。它还提供了大量的运算符来操作单个事件和事件流。

Mutiny 支持文档中查找有关 Mutiny 及其在 Quarkus 中的使用的更多信息。

协程是一种按顺序编写异步代码的方法。它会在 I/O 期间暂停代码的执行,并将代码的其余部分注册为延续。当使用 Kotlin 进行开发并且只需要表达顺序组合(相互依赖的异步任务链)时,Kotlin 协程非常有用。

命令式和响应式的统一

更改您的开发模型并不简单。它需要以非阻塞方式重新学习和重构代码。幸运的是,您不必这样做!

由于其响应式引擎,Quarkus 本质上是响应式的。但是,作为应用程序开发人员,您不必编写响应式代码。Quarkus 统一了响应式和命令式。这意味着您可以在 Quarkus 上编写传统的阻塞应用程序。但是如何避免阻塞 I/O 线程呢?Quarkus 实现了 Proactor 模式,该模式在需要时切换到工作线程。

The proactor pattern in Quarkus

由于代码中的提示(例如 @Blocking@NonBlocking 注解),Quarkus 扩展可以决定应用程序逻辑何时阻塞或非阻塞。如果我们回到上面的 HTTP 端点示例,HTTP 请求始终在 I/O 线程上接收。然后,将该请求调度到您的代码的扩展决定是在 I/O 线程上调用它(避免线程切换)还是在工作线程上调用它。此决定取决于扩展。例如,Quarkus REST(以前的 RESTEasy Reactive)扩展使用 @Blocking 注解来确定是否需要使用工作线程调用该方法,或者是否可以使用 I/O 线程调用该方法。

Quarkus 务实且通用。您可以决定如何开发和执行应用程序。您可以使用命令式方式、响应式方式或混合它们,在应用程序的高并发部分使用响应式。

启用响应式的 Quarkus 扩展

Quarkus 提供了大量的响应式 API 和功能。本节列出了最重要的功能,但这不是一个详尽的列表。Quarkus 在每个版本中都会添加新功能,并且 Quarkiverse 提出了许多启用响应式的扩展。

HTTP

  • Quarkus REST:Jakarta REST 的一个实现,专为 Quarkus 架构量身定制。它遵循响应式优先的方法,但允许使用 @Blocking 注解的命令式代码。

  • Reactive Routes:一种声明性方式,用于直接在 Vert.x 路由器上注册 HTTP 路由,Quarkus 使用该路由器将 HTTP 请求路由到方法。

  • REST Client:允许使用 HTTP 端点。在底层,它使用 Quarkus 的非阻塞 I/O 功能。

  • Qute - Qute 模板引擎公开了一个响应式 API,以非阻塞方式呈现模板。

数据

  • Hibernate Reactive:Hibernate ORM 的一个版本,使用异步和非阻塞客户端与数据库交互。

  • Hibernate Reactive with Panache:在 Hibernate Reactive 之上提供活动记录和存储库支持。

  • Reactive PostgreSQL client:一个与 PostgreSQL 数据库交互的异步和非阻塞客户端,允许高并发性。

  • Reactive MySQL client:一个与 MySQL 数据库交互的异步和非阻塞客户端

  • MongoDB 扩展:公开了一个命令式和响应式 (Mutiny) API,用于与 MongoDB 交互。

  • Mongo with Panache 为命令式和响应式 API 提供活动记录支持。

  • Cassandra 扩展:公开了一个命令式和响应式 (Mutiny) API,用于与 Cassandra 交互

  • Redis 扩展:公开了一个命令式和响应式 (Mutiny) API,用于从 Redis 键值存储中存储和检索数据。

事件驱动架构

  • Reactive Messaging:允许使用响应式和命令式代码实现事件驱动的应用程序。

  • Kafka Connector for Reactive Messaging:允许实现消费和写入 Kafka 记录的应用程序

  • AMQP 1.0 Connector for Reactive Message:允许实现发送和接收 AMQP 消息的应用程序。

网络协议和实用程序

  • gRPC:实现和使用 gRPC 服务。提供响应式和命令式编程接口。

  • GraphQL:使用 GraphQL 实现和查询(客户端)数据存储。提供 Mutiny API 和作为事件流的订阅。

  • Fault Tolerance:为您的应用程序提供重试、回退、断路器功能。它可以与 Mutiny 类型一起使用。

引擎

  • Vert.x:Quarkus 的底层响应式引擎。该扩展允许访问托管的 Vert.x 实例,以及它的 Mutiny 变体(使用 Mutiny 类型公开 Vert.x API)

  • Context Propagation:在响应式管道中捕获和传播上下文对象(事务、主体…)

相关内容