飙血推荐
  • HTML教程
  • MySQL教程
  • JavaScript基础教程
  • php入门教程
  • JavaScript正则表达式运用
  • Excel函数教程
  • UEditor使用文档
  • AngularJS教程
  • ThinkPHP5.0教程

使用 Apache Camel 和 Quarkus 的微服务

时间:2023-06-06  作者:电脑狂魔  

Apache Camel只是 Java 企业堆栈领域的新成员。它由 James Strachan 于 2007 年创建,旨在实现著名的“EIP 书籍”( Gregor Hohpe 和 Bobby Woolf 合着的Enterprise Integration Patterns,Addison Wesley 于 2003 年 10 月出版)。在 2010 年初成为最流行的 Java 集成框架之一之后,Apache Camel 正处于迷失历史的边缘,转而支持一种称为企业服务总线 (ESB) 的新架构模型,并被视为解决问题的灵丹妙药。面向服务的架构(SOA)。 

但在 SOA 惨败之后,Apache Camel(与此同时,它已被多家编辑器采用和分发,包括但不限于 Progress Software 和 Red Hat,以商业名称如 Mediation Router 或 Fuse)正在强势回归并且仍然存在,在下一个十年的整合中更加强大。新的超音速和亚原子 Java 平台Quarkus也让这次回归变得更容易。

本文旨在提出一种非常方便的微服务实现方法,使用 Apache Camel 作为 Java 开发工具,Quarkus 作为运行时,以及不同的 Kubernetes (K8s) 集群——从 Minikube 等本地集群到 EKS(弹性 Kubernetes 服务)、OpenShift 等 PaaS,或 Heroku - 作为基础设施。

该项目

为了说明这一点,这里使用的项目是一个简化的汇款应用程序,由四个微服务组成,如下所示:

  1. aws-camelk-file:此微服务正在轮询本地文件夹,一旦传入 XML 文件,它就会将其存储在新创建的 AWS S3 存储桶中,该存储桶的名称以其开头,后跟一个随机后缀mys3。

  2. aws-camelk-s3:此微服务正在侦听第一个找到的 AWS S3 存储桶,其名称以 开头mys3。一旦收到 XML 文件,它就会对其进行拆分、标记化和流式传输,然后将每条消息发送到 AWS SQS(简单队列服务)队列,该队列名为myQueue.

  3. aws-camelk-sqs:此微服务订阅名为 AWS SQS 队列的消息myQueue,对于每条传入消息,将其从 XML 解组为 Java 对象,然后将其编组为 JSON 格式,然后再将其发送到下面的 REST 服务。

  4. aws-camelk-jaxrs:此微服务公开了一个 REST API,该 API 具有用于 CRUD-ing 汇款订单的端点。它使用/生成 JSON 输入/输出数据。它使用公开模块定义的接口的服务aws-camelk-api。可能存在此接口的多个实现,但为了简单起见,在当前情况下,我们使用名为 的模块定义的接口,aws-camelk-provider它DefaultMoneyTransferProvider仅对内存中哈希映射中的汇款订单请求进行 CRUD。

该项目的源代码可以在这里找到。这是一个多模块的 Maven 项目,模块解释如下。最重要的 Maven 依赖项如下所示:

<dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>域名form</groupId>
        <artifactId>quarkus-bom</artifactId>
        <version>${域名ion}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      <dependency>
        <groupId>域名form</groupId>
        <artifactId>quarkus-camel-bom</artifactId>
        <version>${域名ion}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      <dependency>
        <groupId>域名onaws</groupId>
        <artifactId>aws-java-sdk-bom</artifactId>
        <version>域名</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

模块aws-camelk-model

MoneyTransfer该模块定义了应用程序的域,它由、 、 等业务对象组成。集成应用程序的一个特殊性是业务域是遗留的,通常是几十年前Bank由BankAddress业务分析师和专家设计的,忽略了有关作为软件开发人员,您当前正在使用的工具集。这种遗产有多种形式,例如 Excel 工作表和 CSV 或 XML 文件。

因此,我们在这里考虑经典场景,根据该场景,我们的域模型被定义为由几个 XSD 文件定义的 XML 语法。这些 XSD 文件位于src/main/resources/xsd目录中,并由 处理jaxb2-maven-plugin以生成关联的 Java 对象。下面的清单显示了插件的配置:

<plugin>
        <groupId>域名</groupId>
        <artifactId>jaxb2-maven-plugin</artifactId>
        <dependencies>
          <dependency>
            <groupId>域名2_commons</groupId>
            <artifactId>jaxb2-value-constructor</artifactId>
            <version>3.0</version>
          </dependency>
        </dependencies>
        <executions>
          <execution>
            <goals>
              <goal>xjc</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <packageName>域名域名域名</packageName>
          <sources>
            <source>${basedir}/src/main/resources/xsd</source>
          </sources>
          <arguments>
            <argument>-Xvalue-constructor</argument>
          </arguments>
          <extension>true</extension>
        </configuration>
      </plugin>

在这里,我们正在运行模式编译器工具,以根据项目目录中存在的 XSD 模式xjc在目标包中生成 Java 类。默认情况下,这些自动生成的具有JAXB(Java XML 绑定体系结构)注释的 Java 对象没有构造函数,这使得它们使用起来有点困难,尤其是对于具有许多必须通过 setter 实例化的属性的类。因此,在上面的清单中,我们配置了对工件的依赖。为此,我们要求编译器为每个后续的 JAXB 处理类生成完整的参数构造函数。域名域名域名src/main/resources/xsdjaxb2-maven-pluginjaxb3-value-constructorxjc

该模块的最终结果是一个 JAR 文件,其中包含以 Java 类层次结构形式存在的领域模型,该文件将用作所有其他应用程序模块的依赖项。这种方法比由 XML 语法定义的域对象的手动实现(同样是在 Java 中)组成的方法实用得多。

模块aws-camelk-api

这个模块非常简单,因为它只包含一个接口。这个名为 的接口MoneyTransferFacade是汇款服务公开的接口。该服务必须实现公开的接口。实际上,此类服务可能有许多不同的实现方式,具体取决于汇款的性质、银行、客户类型和许多其他可能的标准。在我们的示例中,我们只考虑此接口的简单实现,如下一节所示。

模块aws-camelk-provider

该模块定义接口的服务提供者MoneyTransferFacade。这里使用的 SPI(软件提供者接口)模式非常强大,允许将服务接口与其实现分离。

我们接口的实现MoneyTransferFacade是类DefaultMoneyTransferProvider,它也非常简单,因为它只在内存中的哈希映射中对汇款订单进行增删改查。

模块aws-camelk-jaxrs

与之前仅是通用类库的模块不同,此模块和下一个模块是 Quarkus 可运行服务。这意味着他们使用quarkus-maven-plugin来创建可执行 JAR。

顾名思义,该模块公开了一个 JAX-RS(用于 RESTfull Web 服务的 Java API)API 来处理汇款订单。Quarkus 附带 RESTeasy,这是 Red Hat 对 JAX-RS 规范的完整实现,这就是我们在这里使用的。

MoneyTransferResource就实现REST API的类而言,没有什么特别值得一提的。它提供了用于创建、读取、更新和删除汇款单的端点,此外,还提供了两个旨在检查应用程序的活动性和就绪性的端点。

模块aws-camelk-file

该模块是 Camel 管道中的第一个模块,包括将包含汇款订单的 XML 文件从其初始登陆目录传送到 REST API,REST API 代表服务提供商处理它​​们。它使用 Camel Java DSL(领域特定语言)来做到这一点,如下面的清单所示:

fromF("file://%s?include=.*.xml&delete=true&idempotent=true&bridgeErrorHandler=true", inBox)
      .doTry()
        .to("validator:xsd/money-域名")
        .setHeader(域名, header(域名_NAME))
        .to(aws2S3(s3Name + RANDOM).autoCreateBucket(true).useDefaultCredentialsProvider(true))
      .doCatch(域名s)
        .log(域名R, failureMsg + " ${域名age}")
      .doFinally()
      .end();

此代码轮询定义为外部属性的输入目录是否存在任何 XML 文件(具有 .xml扩展名的文件)。一旦这样的文件进入给定目录,就会根据src/main/resources/xsd/money-域名文件中定义的模式对其进行验证。如果有效,它将存储在 AWS S3 存储桶中,其名称计算为等于外部定义的常量后跟随机后缀。一切都封装在一个try...catch结构中,以一致地处理异常情况。

在这里,为了定义外部属性,我们使用由 Quarkus 实现的 Eclipse MP 配置规范(以及其他规范),如下面的清单所示:

private static final String RANDOM = new Random().ints('a', 'z')
    .limit(5)
    .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
    .toString();
  @ConfigProperty(name="inBox")
  String inBox;
  @ConfigProperty(name="s3Name")
  String s3Name;

后缀RANDOM代表类域名om和属性生成inBox ,并s3Name从文件中注入src/resource/域名erties。之所以使用由常量和随机后缀组成的S3 bucket名称是因为AWS S3 bucket需要具有跨区域的唯一名称,因此,我们需要这样一个随机后缀来保证唯一性。

模块aws-camelk-s3

该模块实现了一个 Camel 路由,每当文件到达专用 S3 存储桶时,该路由就会由 AWS 基础设施触发。这是代码:

 

from(aws2S3(s3BucketName).useDefaultCredentialsProvider(true))
      .split().tokenizeXML("moneyTransfer").streaming()
      .to(aws2Sqs(queueName).autoCreateQueue(true).useDefaultCredentialsProvider(true));

一旦触发,Camel 路由会在标记化输入 XML 文件后按顺序拆分输入 XML 文件。这个想法是一个输入文件可能包含多个汇款订单,这些订单将被单独处理。queueName因此,从此标记化和拆分过程发出的每个单一汇款订单都被发送到 AWS SQS 队列,该队列的名称由从文件注入的属性值指定域名erties。

模块aws-camelk-sqs

这是我们 Camel 管道的最后一个模块。

from(aws2Sqs(queueName).useDefaultCredentialsProvider(true))
      .unmarshal(jaxbDataFormat)
      .marshal().json(域名b)
      .setHeader(域名_METHOD, constant("POST"))
      .to(http(uri));

此 Camel 路由订阅 AWS SQS 队列,其名称由属性指定queueName,并将接收到的每个 XML 消息解组为 Java 对象。鉴于每个 XML 消息都包含一个汇款单,它在相应的MoneyTransferJava 类实例中被解组。然后,一旦解组,每个MoneyTransferJava 类实例将再次编组为 JSON 负载。这是必需的,因为我们的 REST 接口使用 JSON 有效负载,并且与能够自动执行从 Java 对象到 JSON 的转换的标准 JAX-RS 客户端相反,http()这里使用的骆驼组件不是。因此,我们需要手动完成。通过将交换的标头设置为 POST 常量,我们设置将发送到 REST API 的 HTTP 请求的类型。最后但同样重要的是,端点 URI 像往常一样作为外部定义的属性从域名erties文件中注入。

单元测试

在部署和运行我们的微服务之前,我们需要对它们进行单元测试。该项目包括几乎所有模块的几个单元测试 - 从aws-camelk-model,测试域模型的地方,以及它从/到 XML/Java 的各种转换,到aws-camelk-jaxrs,这是我们的终点微服务。为了运行单元测试,这很简单。只需执行:

$ cd aws-camelk
$ ./delete-all-域名#Delete all the buckets named "mys3*" if any
$ ./purge-sqs-域名#Purge the SQS queue named myQueue if it exists and isn't empty
$ mvn clean package#Clean-up, run unit tests and create JARs

将显示完整的单元测试报告maven-surefile-plugin。为了单元测试按预期运行,需要一个 AWS 帐户,并且应该在本地机器上安装和配置 AWS CLI。这意味着,除其他外,该文件~/.aws/credentials包含您的aws_access_key_id以及aws_secret_access_key properties它们的关联值。

原因是单元测试使用 AWS SDK(软件开发工具包)来处理 S3 存储桶和 SQS 队列,这使得它们不完全是单元测试,而是单元测试和集成测试的组合。

部署和运行

现在,要部署和运行我们的微服务,我们必须考虑许多不同的场景——从简单的本地独立执行到 PaaS 部署(如OpenShift或 EKS)通过本地 K8s 集群(如 Minikube)。因此,为了避免此处出现一些混乱,我们更愿意为每个此类部署场景专门写一篇文章。

因此,请靠近您的浏览器,看看接下来的故事会把我们带到哪里。


湘ICP备14001474号-3  投诉建议:234161800@qq.com   部分内容来源于网络,如有侵权,请联系删除。