使用 Apache Camel 和 Quarkus 的微服务(一)

2023-10-07 20:20

本文主要是介绍使用 Apache Camel 和 Quarkus 的微服务(一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【squids.cn】 全网zui低价RDS,免费的迁移工具DBMotion、数据库备份工具DBTwin、SQL开发工具等

​Apache Camel 绝非Java企业技术栈领域的新手。它由James Strachan在2007年创建,旨在实现著名的 "EIP 书"(由Gregor Hohpe和Bobby Woolf编写,Addison Wesley于2003年10月出版的企业集成模式)。在2010年初成为最受欢迎的Java集成框架之一后,Apache Camel正处于被历史所遗忘的边缘,原因是人们更青睐一种名为企业服务总线(ESB)的新架构模型,并视其为面向服务架构(SOA)的灵丹妙药。

然而,在SOA失败后,Apache Camel(与此同时,已被包括但不限于Progress Software和Red Hat的多家编辑采纳,并以商业名称如Mediation Router或Fuse进行分发)正在强势回归,并且为下一个集成的十年变得更为强大。这种复出也得益于Quarkus,这是一个新的超音速和次原子Java平台。

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

项目概述

本项目旨在通过一个简化的货币转账应用程序来阐明相关观点,该程序包含四个微服务,具体如下:

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

aws-camelk-s3: 该微服务监听首个找到的AWS S3 bucket,该bucket的名称以mys3开头。一旦有XML文件传入,它将对文件进行分割、标记化和流处理,然后将每个消息发送到名为myQueue的AWS SQS(简单队列服务)队列。 

aws-camelk-sqs: 该微服务订阅名为myQueue的AWS SQS队列上的消息,并对每个传入消息执行从XML到Java对象的解组操作,然后将其组织为JSON格式,再将其发送到下面的REST服务。 

aws-camelk-jaxrs: 该微服务提供了一个REST API,具有用于创建、读取、更新和删除货币转账订单的端点。它接收/生成JSON输入/输出数据。它使用一个服务,该服务展现了由aws-camelk-api模块定义的接口。可能存在此接口的多个实现,但为简单起见,在当前情况下,我们使用由aws-camelk-provider模块定义并命名为DefaultMoneyTransferProvider的实现,该实现仅在内存哈希图中处理货币转账订单请求。 

项目的源代码可以在此处找到。这是一个多模块的Maven项目,下面解释了各个模块。下面显示了最重要的Maven依赖项:

  <dependencyManagement>    <dependencies>      <dependency>        <groupId>io.quarkus.platform</groupId>        <artifactId>quarkus-bom</artifactId>        <version>${quarkus.platform.version}</version>        <type>pom</type>        <scope>import</scope>      </dependency>      <dependency>        <groupId>io.quarkus.platform</groupId>        <artifactId>quarkus-camel-bom</artifactId>        <version>${quarkus.platform.version}</version>        <type>pom</type>        <scope>import</scope>      </dependency>      <dependency>        <groupId>com.amazonaws</groupId>        <artifactId>aws-java-sdk-bom</artifactId>        <version>1.12.454</version>        <type>pom</type>        <scope>import</scope>      </dependency>    </dependencies>  </dependencyManagement>

模块 aws-camelk-model 

此模块定义了应用程序的域,该域由诸如MoneyTransfer、Bank、BankAddress等业务对象组成。集成应用的特点之一是其业务域是遗留的,通常是几十年前由忽略了您作为软件开发者当前正在使用的工具集的业务分析师和专家设计的。这种遗留以各种形式存在,如Excel表格以及CSV或XML文件。

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

      <plugin><groupId>org.codehaus.mojo</groupId><artifactId>jaxb2-maven-plugin</artifactId><dependencies><dependency><groupId>org.jvnet.jaxb2_commons</groupId><artifactId>jaxb2-value-constructor</artifactId><version>3.0</version></dependency></dependencies><executions><execution><goals><goal>xjc</goal></goals></execution></executions><configuration><packageName>fr.simplex_software.quarkus.camel.integrations.jaxb</packageName><sources><source>${basedir}/src/main/resources/xsd</source></sources><arguments><argument>-Xvalue-constructor</argument></arguments><extension>true</extension></configuration></plugin>

在这里,我们运行xjc模式编译器工具,在目标包fr.simplex_software.quarkus.camel.integrations.jaxb中基于项目的src/main/resources/xsd目录中的XSD模式生成Java类。默认情况下,这些自动生成的Java对象具有JAXB(Java Architecture for XML Binding)注释,但没有构造函数,这使得它们有点难以使用,特别是对于必须通过setter实例化的具有许多属性的类。因此,在上面的列表中,我们将jaxb2-maven-plugin配置为依赖于jaxb3-value-constructor工件。通过这样做,我们要求xjc编译器为每个随后的JAXB处理类生成完整参数构造函数。

此模块的最终结果是一个JAR文件,其中包含我们的领域模型,形式为Java类层次结构,所有其他应用程序模块将其用作依赖项。这种方法比手动实现(再次,用Java)由XML语法已经定义的域对象的方法更为实用。

模块 aws-camelk-api 

此模块非常简单,因为它仅由一个接口组成。这个接口名为MoneyTransferFacade,是由资金转账服务公开的接口。此服务必须实现公开的接口。实际上,这样的服务可能有许多不同的实现,具体取决于资金转移的性质、银行、客户类型以及许多其他可能的条件。在我们的例子中,我们只考虑了该接口的简单实现,如下一节所示。

模块 aws-camelk-provider 

此模块为MoneyTransferFacade接口定义了服务提供商。在这里使用的SPI(Software Provider Interface,软件提供商接口)模式是非常强大的,它允许将服务接口与其实现解耦。

我们对MoneyTransferFacade接口的实现是DefaultMoneyTransferProvider类,它也非常简单,因为它只是在内存哈希映射中创建、读取、更新和删除资金转账订单。

模块 aws-camelk-jaxrs 

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

如其名称所示,此模块公开了一个JAX-RS(Java API for RESTful Web Services)API来处理资金转账订单。Quarkus带有RESTeasy,这是Red Hat对JAX-RS规范的完全实现,这就是我们在这里使用的。

就MoneyTransferResource类而言,没有什么特别的要提及的,该类实现了REST API。它提供了创建、读取、更新和删除资金转账订单的端点,并且额外提供了两个端点,目的是检查应用程序的活动状态和准备状态。

模块 aws-camelk-file 

此模块是Camel管道中的第一个模块,由此模块将包含资金转账订单的XML文件从其初始登陆目录传送到REST API,该API代表服务提供商处理它们。它使用Camel Java DSL(Domain Specific Language,领域特定语言)来执行此操作,如下面的列表所示:

fromF("file://%s?include=.*.xml&delete=true&idempotent=true&bridgeErrorHandler=true", inBox).doTry().to("validator:xsd/money-transfers.xsd").setHeader(AWS2S3Constants.KEY, header(FileConstants.FILE_NAME)).to(aws2S3(s3Name + RANDOM).autoCreateBucket(true).useDefaultCredentialsProvider(true)).doCatch(ValidationException.class).log(LoggingLevel.ERROR, failureMsg + " ${exception.message}").doFinally().end();

该代码轮询一个输入目录,该目录被定义为一个外部属性,以检查任何XML文件(具有.xml扩展名的文件)的存在。一旦这样的文件落在给定的目录中,它将根据src/main/resources/xsd/money-transfers.xsd文件中定义的模式进行验证。如果验证有效,它将被存储在一个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代表类java.util.Random和属性生成inBox ,并s3Name从文件中注入src/resource/application.properties。使用由常量和随机后缀组成的S3存储桶名称的原因是AWS S3存储桶需要具有跨区域唯一的名称,因此,我们需要这样的随机后缀来保证唯一性。

模块aws-camelk-s3

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

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

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

模块aws-camelk-sqs

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

    from(aws2Sqs(queueName).useDefaultCredentialsProvider(true))      .unmarshal(jaxbDataFormat)      .marshal().json(JsonLibrary.Jsonb)      .setHeader(Exchange.HTTP_METHOD, constant("POST"))      .to(http(uri));

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

单元测试

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


$ cd aws-camelk
$ ./delete-all-buckets.sh  #Delete all the buckets named "mys3*" if any
$ ./purge-sqs-queue.sh  #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队列,这使得它们不完全是单元测试,而是单元测试和集成测试的组合。

部署和运行

现在,要部署和运行我们的微服务,我们需要考虑许多不同的情景 - 从简单的本地独立执行到像OpenShift或EKS这样的PaaS部署,再到像Minikube这样的本地K8s集群。因此,为了避免在这里产生一些混淆,我们更倾向于为每种部署情景单独撰写一篇文章。

所以请关注下一篇文章。

作者:Nicolas Duminil

更多内容请关注公号【云原生数据库

squids.cn,云数据库RDS,迁移工具DBMotion,云备份DBTwin等数据库生态工具。

这篇关于使用 Apache Camel 和 Quarkus 的微服务(一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/160214

相关文章

vue使用docxtemplater导出word

《vue使用docxtemplater导出word》docxtemplater是一种邮件合并工具,以编程方式使用并处理条件、循环,并且可以扩展以插入任何内容,下面我们来看看如何使用docxtempl... 目录docxtemplatervue使用docxtemplater导出word安装常用语法 封装导出方

Linux换行符的使用方法详解

《Linux换行符的使用方法详解》本文介绍了Linux中常用的换行符LF及其在文件中的表示,展示了如何使用sed命令替换换行符,并列举了与换行符处理相关的Linux命令,通过代码讲解的非常详细,需要的... 目录简介检测文件中的换行符使用 cat -A 查看换行符使用 od -c 检查字符换行符格式转换将

使用Jackson进行JSON生成与解析的新手指南

《使用Jackson进行JSON生成与解析的新手指南》这篇文章主要为大家详细介绍了如何使用Jackson进行JSON生成与解析处理,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 核心依赖2. 基础用法2.1 对象转 jsON(序列化)2.2 JSON 转对象(反序列化)3.

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当

Java中List的contains()方法的使用小结

《Java中List的contains()方法的使用小结》List的contains()方法用于检查列表中是否包含指定的元素,借助equals()方法进行判断,下面就来介绍Java中List的c... 目录详细展开1. 方法签名2. 工作原理3. 使用示例4. 注意事项总结结论:List 的 contain

C#使用SQLite进行大数据量高效处理的代码示例

《C#使用SQLite进行大数据量高效处理的代码示例》在软件开发中,高效处理大数据量是一个常见且具有挑战性的任务,SQLite因其零配置、嵌入式、跨平台的特性,成为许多开发者的首选数据库,本文将深入探... 目录前言准备工作数据实体核心技术批量插入:从乌龟到猎豹的蜕变分页查询:加载百万数据异步处理:拒绝界面

Android中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(

Python使用自带的base64库进行base64编码和解码

《Python使用自带的base64库进行base64编码和解码》在Python中,处理数据的编码和解码是数据传输和存储中非常普遍的需求,其中,Base64是一种常用的编码方案,本文我将详细介绍如何使... 目录引言使用python的base64库进行编码和解码编码函数解码函数Base64编码的应用场景注意