Quarkus 超级英雄来救援!

您是否正在构建微服务的开发者?您是否在开发和测试构成大型系统一部分的独立微服务时遇到困难?您想了解如何构建基于 REST 和事件驱动的应用程序吗?
简介
Quarkus 拥有出色的 文档 和 快速入门示例,可以帮助开发者熟悉 Quarkus 生态系统中的各种功能。然而,缺少的是一套充分实现的真实世界应用程序示例,这些示例使用这些功能、模式和最佳实践,同时还能反映 Quarkus 试图解决的问题。
本文介绍了 Quarkus Superheroes 示例应用程序,讨论了构建它的某些要求,并说明了如何在本地运行它或将其部署到 Kubernetes。您还可以观看介绍它的 Quarkus Insights 节目。
要求
除了单纯的乐趣之外,还有一些其他要求也很重要
-
整体架构应为多服务微服务架构。
-
它需要不仅仅是“hello world”,但也不是“包罗万象”,而是选择一套通用功能,例如 REST、WebSockets、数据库交互、消息传递、健康检查、监控/指标、Apache Avro 和 OpenAPI 集成。
-
应用程序应与每个 Quarkus 版本保持同步,并成为 标准 Quarkus 生态系统持续集成 的一部分,并在 Quarkus 状态仪表板 上显示。
-
尽可能同时提供阻塞和响应式示例。
-
整个系统应该
-
易于在本地开发机器或 Kubernetes 上构建、运行、部署和演示。
-
展示 Quarkus 如何帮助促进独立微服务的本地开发。
-
为了简单起见,应包含在 单个 GitHub 存储库 中,但 **不是** 多模块项目。
-
-
系统中的每个应用程序都应
-
易于在本地开发机器或 Kubernetes 上构建、运行、部署和演示。
-
为 Java 11 和 17 版本提供 容器镜像,包括 JVM 和原生。
-
拥有完整的文档。
-
拥有完全自动化(且有文档)的 CI/CD 实践。
-
包含完整的单元测试和集成测试套件。
-
初始发布
Quarkus Superheroes 应用程序的初始版本于 2022 年 2 月初发布。多个微服务共存形成一个更大的系统,通过 REST 进行同步通信或通过 Apache Kafka 进行事件驱动通信。其中一些应用程序是响应式的,而另一些则更传统,展示了如何构建每种类型。
基于 Web 的用户界面(如图 1 所示)允许超级英雄与超级反派作战。之前的战斗结果也显示在此页面上。

另一个用户界面(如图 2 所示)显示了之前的战斗统计数据,包括英雄与反派的胜率以及前 10 名获胜者及其各自的获胜次数。

幕后揭秘!
图 3 显示了应用程序的整体架构。

有四个 Quarkus 应用程序(下文将进一步介绍),一个 Angular 应用程序,以及一些后端服务:Prometheus、PostgreSQL、Apache Kafka 和 Apicurio Schema Registry。
英雄服务
Hero 服务是一个完全响应式且非阻塞的 HTTP 微服务,公开了 Hero
数据模型上的 CRUD 操作。REST 层使用 RESTEasy Reactive 和响应式端点实现。数据使用 Panache 的 Quarkus Hibernate Reactive 的 存储库模式 持久化到 PostgreSQL 数据库。此外,Hero 服务倾向于使用 Bean 的 构造函数注入 而不是 字段注入。Hero 服务包含一套完整的单元和集成测试,使用 模拟、间谍,并在 隔离的事务 中进行测试。
为了确保快速启动时间,数据库中仅加载了来自 3,458 位可用英雄 中的 100 位随机英雄。如果您想加载更多数据,请从仓库的 |
反派服务
Villain 服务是一个阻塞式 HTTP 微服务,公开了 Villain
数据模型上的 CRUD 操作。事实上,Villain
数据模型与 Hero 服务 中的 Hero
数据模型相同(除了表的名称)。它还实现了与 Hero 服务相同的用例。唯一的区别是 Villain 服务是阻塞的,并且它使用了 Panache 的 Quarkus Hibernate ORM 的 Active Record 模式。
REST 层使用 RESTEasy Reactive 和阻塞端点实现。数据持久化到 PostgreSQL 数据库。Villain 服务还创建了一些自定义配置,展示了如何使用 ConfigMapping
对象。此外,Villain 服务倾向于使用 Bean 的 字段注入 而不是 构造函数注入。Villain 服务包含一套完整的单元和集成测试,使用 模拟、间谍,并在 隔离的事务 中进行测试。
为了确保快速启动时间,数据库中仅加载了来自 1,797 位可用反派 中的 100 位随机反派。如果您想加载更多数据,请从仓库的 |
战斗服务
Fight 服务是一个完全响应式且非阻塞的 HTTP 微服务,公开了用于进行英雄与反派之间战斗的 RESTful API。REST 层使用 RESTEasy Reactive 和响应式端点实现。战斗数据使用 Panache 的 Quarkus MongoDB Reactive 的 Active Record 模式 持久化到 MongoDB 数据库。Fight 服务还倾向于使用 Bean 的 构造函数注入 而不是 字段注入。
Fight 服务向 Hero 和 Villain 服务发出出站 REST 调用。对 Hero 服务的调用使用 响应式 REST 客户端,而对 Villain 服务的调用使用 RESTEasy Reactive 客户端,这是一个 MicroProfile Rest Client 实现,基于 JAX-RS 客户端 API,其核心是非阻塞的。所有出站调用都使用 弹性模式,如 重试、超时、回退 和 断路器。
此外,Fight 服务以 Apache Avro 格式向 Kafka 发出 战斗事件。战斗模式由 Quarkus Apicurio Avro 扩展 自动注册到 Apicurio Schema Registry 中。
Fight 服务包含一套完整的单元和集成测试,使用 模拟、间谍,并在 隔离的事务 中进行测试。它还大量使用 Wiremock 来模拟下游 REST 端点,以及一个 内存 Kafka 连接器 来在单元测试中执行消息验证。它还展示了如何 注入 Dev Services 信息 来配置测试资源,例如 KafkaConsumer
。
事件统计服务
Event Statistics Service 是一个事件驱动的微服务,公开了一个 WebSocket HTTP 层。它使用 SmallRye Reactive Messaging 监听 Kafka 主题上的 Apache Avro 格式的战斗事件。战斗模式由 Quarkus Apicurio Avro 扩展 自动注册到 Apicurio Schema Registry 中。
统计信息通过基于浏览器的用户界面显示(如上文图 2 所示)。团队统计数据按英雄与反派的胜率百分比累积。获胜者统计数据按每个英雄或反派的获胜次数累积,并保留前 10 名获胜者。统计数据通过 WebSockets 推送到 UI。
Event Statistics 服务包含一套完整的单元和集成测试,使用 模拟 和 间谍。它还展示了如何 注入 Dev Services 信息 来配置测试资源,例如 KafkaProducer
。
超级英雄 UI
Super Hero UI 应用程序(如上文图 1 所示)是一个通过 Node.js 部署的 Angular 单页应用程序。它通过 REST 与 Fight 服务通信。此示例应用程序的重点是 Quarkus 应用程序,而不是 Angular UI。
本地运行应用程序
根据您的目标,有几种方法可以在本地运行应用程序。如果想运行 整个应用程序 或 其中的一部分,可以使用 Docker Compose,使用 预构建的容器镜像。或者,每个应用程序都可以 从源代码运行。
通过 Docker Compose 本地运行
可以使用单个 Docker Compose 命令来启动整个应用程序或其中的一部分。
运行整个应用程序
存储库 根目录 中的 deploy/docker-compose
目录包含应用程序的四个版本(JVM 11、JVM 17、使用 Java 11 构建的本地版本、使用 Java 17 构建的本地版本)的 compose 文件。此外,还可以使用 提供的 prometheus.yml
文件 启动 Prometheus 监控。
在 quarkus-super-heroes 目录中,只需根据您想运行的应用程序版本运行 命令 即可。例如,要运行本地 Java 17 版本,请运行 docker-compose -f deploy/docker-compose/native-java17.yml -f deploy/docker-compose/prometheus.yml up
。
存储库 scripts
目录包含一个可以在单独终端中运行的 watch-services.sh
脚本。此脚本将监视所有服务的启动,并在它们全部启动并就绪时报告。
在应用程序启动时,您可能会看到错误。如果一个服务在其所需的某个服务(例如数据库、Kafka 代理等)之前完成启动,则可能会发生这种情况。一旦所有服务完成启动,它们就会按预期工作。 |
所有服务就绪后,将提供以下 URL:
-
超级英雄 UI:https://:8080
-
事件统计 UI:https://:8085
-
Apicurio Schema Registry:https://:8086
-
Prometheus:https://:9090
-
Fight 服务:https://:8082
-
Hero 服务:https://:8083
-
Villain 服务:https://:8084
运行应用程序的一部分
也可以通过 Docker Compose 运行每个单独的服务。
在存储库中每个服务的子目录中,都有一个 deploy/docker-compose
目录,其中包含应用程序的四个版本的 compose 文件。可以将多个 compose 文件合并到一个命令中。
这在您想在 Quarkus Dev Mode 中处理 Fight 服务,并且需要 Hero 和 Villain 服务可用时非常有用。在 quarkus-super-heroes
目录中,只需根据您想运行的应用程序版本运行 命令。例如,要运行本地 Java 17 版本,请运行 docker-compose -f rest-heroes/deploy/docker-compose/native-java17.yml -f rest-villains/deploy/docker-compose/native-java17.yml up
。
通过 Quarkus Dev Mode 本地运行
每个服务都可以通过 Quarkus Dev Mode 同时运行。对于每个 Quarkus 服务(event-statistics
、rest-fights
、rest-heroes
、rest-villains
),打开一个终端,cd
进入项目目录,然后运行 ./mvnw quarkus:dev
。
Super Heroes UI 可以 从源代码构建和运行,但由于本文的重点是 Quarkus,我们将它作为一个容器镜像运行。打开一个新的终端并运行 docker run -p 8080:8080 -e API_BASE_URL=https://:8082 quay.io/quarkus-super-heroes/ui-super-heroes:latest
。
所有服务就绪后,将提供以下 URL:
-
超级英雄 UI:https://:8080
-
事件统计 UI:https://:8085
-
Fight 服务:https://:8082
-
Hero 服务:https://:8083
-
Villain 服务:https://:8084
现在,您将拥有 Quarkus Dev Mode 和 Quarkus Continuous Testing 的所有优势,覆盖整个应用程序!所有后端基础设施(数据库、Kafka、Apicurio)都由 Quarkus Dev Services 自动为您配置。
将应用程序部署到 Kubernetes
为各种 Kubernetes 版本提供了 Kubernetes 描述符:OpenShift、Minikube、KNative 和“标准” Kubernetes。
Minikube 和 Kubernetes 描述符之间的唯一真正区别是,Minikube 描述符中的所有应用程序 KNative 描述符对这五个应用程序中的每一个都使用了 KNative Serving。 |
与 Docker Compose 类似,可以使用单个 kubectl apply -f
(如果使用 OpenShift,则为 oc apply -f
)将整个应用程序或其中的一部分的 预构建容器镜像 部署到 Kubernetes。
存储库 根目录 中的 deploy/k8s
目录包含应用程序的四个版本(JVM 11、JVM 17、使用 Java 11 构建的本地版本、使用 Java 17 构建的本地版本)的 Kubernetes 描述符。
例如,要将本地 Java 17 版本部署到 OpenShift,只需运行 kubectl apply -f deploy/k8s/native-java17-openshift.yml
(或 oc apply -f deploy/k8s/native-java17-openshift.yml
)。
要部署 Prometheus 监控以及应用程序,请根据目标 Kubernetes 环境运行适当的 Prometheus Kubernetes 描述符(kubectl apply -f
或 oc apply -f
):prometheus-openshift.yml
、prometheus-minikube.yml
或 prometheus-kubernetes.yml
。
在 Minikube 或 Kubernetes 上,只有 Super Heroes UI 和 Fights 服务会暴露在集群外部。如果您想访问 Prometheus 或 Event Statistics 服务,则需要将其公开,方法是使用 Ingress 或进行 kubectl port-forward 到 Pod。在 OpenShift 上,所有应用程序都有 Route ,可以将它们暴露在集群外部。 |
此外,也可以通过类似的方式部署各个应用程序。在存储库中每个服务的子目录中,都有一个 deploy/k8s
目录,其中包含类似的 Kubernetes 描述符矩阵。
这些描述符 **不** 被认为是生产就绪的。它们足够基本,可以以最少的配置来部署和运行系统。部署的数据库、Kafka 代理和模式注册表不具备高可用性,也不使用任何 Kubernetes 运算符进行管理或监控。它们还只使用临时存储。 对于生产就绪的 Kafka 代理,请参阅 Strimzi 文档,了解如何在 Kubernetes 上正确部署和配置生产就绪的 Kafka 代理。您还可以尝试一个 完全托管的 Kafka 服务! 对于生产就绪的 Apicurio Schema Registry,请参阅 Apicurio Registry Operator 文档。您还可以尝试一个 完全托管的 Schema Registry 服务! 对于生产就绪的 Prometheus 实例,请参阅 Prometheus Operator 文档,了解如何正确部署和配置生产就绪的实例。 |
部署到 Kubernetes 后,可能性是无限的!重用上面相同的示例(开发 Fight 服务),您可以使用 Quarkus 远程开发模式将远程实例连接到您的本地机器,并获得类似于 Quarkus Dev Mode 的体验。无需进行任何端口转发!