使用 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等数据库生态工具。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/97063.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2.5 数字传输系统

笔记&#xff1a; 针对这一节的内容&#xff0c;我为您提供一个笔记的整理方法。将内容按重要性、逻辑关系进行组织&#xff0c;再进行简化。 ## 2.5 数字传输系统 ### 背景介绍&#xff1a; 1. **早期电话网**&#xff1a;市话局到用户采用双绞线电缆&#xff0c;长途干线采…

汇总开源大模型的本地API启动方式

文章目录 CodeGeex2ChatGLM2_6BBaichuan2_13Bsqlcoder开启后测试 CodeGeex2 from fastapi import FastAPI, Request from transformers import AutoTokenizer, AutoModel import uvicorn, json, datetime import torch import argparse try:import chatglm_cppenable_chatglm_…

git stash详解

stash:保存现场 1.建议&#xff08;规范&#xff09; &#xff1a;在功能未没有开发完毕前&#xff0c;不要commit 2.规定&#xff08;必须&#xff09; &#xff1a; 在没有commit之前&#xff0c;不能chekcout切换分支 &#xff08;不在同一个commit阶段&#xff09; 如果还没…

缓存与数据库双写一致性问题解决方案

其实如果使用缓存&#xff0c;就会出现缓存和数据库的不一致问题&#xff0c;关键在于我们可以接受不一致的时间是多少&#xff0c;根据不同的需求采取不同的实现方案。 第一种&#xff1a;先更新数据库后更新缓存 做法简单&#xff0c;但是并发写情况下&#xff0c;会出现数…

Mac安装GYM遇到的一些坑

以下是遇到的一些问题 安装GitHub上说的直接 pip install gym成功了&#xff0c;但是运行实例报错没安装gym[classic_control]&#xff0c;所以就全安装一下[all] 安装GitHub上说的直接 pip install gym成功了&#xff0c;但是运行实例报错没安装gym[classic_control]&#xff…

nodejs+vue快递管理服务系统elementui

电子商务改变了人们的传统经济活动中的交易方式和流通技术&#xff0c; 复杂的物流快递信息需要有效的进行处理&#xff0c;构建一个快递管理服务系统可以确保物流信息的一致性、员工登录&#xff1a;通过用户名和密码登录。这也间接带动了物流快递行业的高速发展。 &#xff0…

运行huggingface Kosmos2报错 nameerror: name ‘kosmos2tokenizer‘ is not defined

尝试运行huggingface上的Kosmos,https://huggingface.co/ydshieh/kosmos-2-patch14-224失败,报错: nameerror: name kosmos2tokenizer is not defined查看报错代码: vi /root/.cache/huggingface/modules/transformers_modules/ydshieh/kosmos-2-patch14-224/48e3edebaeb…

用rabbitMq 怎么处理“延迟消息队列”?

延迟消息队列是一种允许消息在发送后等待一段时间&#xff0c;然后再被消费的机制。这种机制通常用于需要延迟处理的应用场景&#xff0c;如定时任务、消息重试、消息调度等。在 RabbitMQ 中&#xff0c;实现延迟消息队列需要使用一些额外的组件和技术&#xff0c;因为 RabbitM…

一天一八股——TCP保活keepalive和HTTP的Keep-Alive

TCP属于传输层&#xff0c;关于TCP的设置在内核态完成 HTTP属于用户层的协议&#xff0c;主要用于web服务器和浏览器之间的 http的Keep-Alive都是为了减少多次建立tcp连接采用的保持长连接的机制&#xff0c;而tcp的keepalive是为了保证已经建立的tcp连接依旧可用(双端依旧可以…

KylinOSv10系统k8s集群启动mysql5.7占用内存高的问题

问题现象 麒麟系统搭建k8s集群 mysql的pod启动失败 describe查看ommkill&#xff0c;放大limit资源限制到30G依旧启动失败 系统 报错信息 原因 内存占用太高 open_files_limit初始化太高 解决&#xff1a; 1、更换镜像 链接: https://pan.baidu.com/s/1b9uJLcc5Os0uDqD1e…

3. 无重复字符的最长子串(枚举+滑动窗口)

目录 一、题目 二、代码 一、题目 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 二、代码 class Solution { public:int lengthOfLongestSubstring(string s) {int _MaxLength 0;int left 0, right 0;vector<int>hash(128, 0);//ASCII…

Spring AOP(JavaEE进阶系列5)

目录 前言&#xff1a; 1.什么是Spring AOP 2.为什么要使用AOP呢&#xff1f; 3.AOP的组成 3.1切面 3.2切点 3.3通知 3.4连接点 4.Spring AOP的实现 4.1添加依赖 4.2定义切面 4.3定义切点 4.4实现通知 5.AOP的实现原理 结束语&#xff1a; 前言&#xff1a; 在…

element ui中父子组件共用一个el-dialog弹窗,切换组件页面弹窗进行关闭

在Element UI中&#xff0c;如果多个父子组件共用一个el-dialog弹窗&#xff0c;并且需要在切换组件页面时关闭弹窗&#xff0c;你可以考虑以下方法来实现&#xff1a; 使用Vuex进行状态管理&#xff1a; 在Vuex中创建一个状态来管理弹窗的显示状态&#xff08;例如&#xff0…

NOSQL Redis 数据持久化 RDB、AOF(二) 恢复

redis 执行flushall 或 flushdb 也会产生dump.rdb文件&#xff0c;但里面是空的。 注意&#xff1a;千万执行&#xff0c;不然rdb文件会被覆盖的。 dump.rdb 文件如何恢复数据 讲备份文件 dump.rdb 移动到redis安装目录并启动服务即可。 dump.rdb 自动触发 和手动触发 自…

【GIT版本控制】--项目管理与工具

一、使用Git与项目管理工具的集成 将Git与项目管理工具集成在一起可以有效地跟踪和管理软件开发项目。以下是如何使用Git与项目管理工具&#xff08;如GitHub、GitLab、Bitbucket和Jira&#xff09;进行集成的关键方法&#xff1a; 创建问题或任务&#xff1a; 项目管理工具通…

IDEA 2023.1.3图文安装教程及下载

IDEA 2023.1 最新变化是在 IDEA 2023.1 中&#xff0c;对新 UI 做出了大量改进。实现了性能增强&#xff0c;从而更快导入 Maven&#xff0c;以及在打开项目时更早提供 IDE 功能。 新版本通过后台提交检查提供了简化的提交流程。 IntelliJ IDEA Ultimate 现在支持 Spring Secur…

智慧电力物联网系统引领电力行业数字化发展

智慧电力物联网系统是以提高用户侧电力运行安全、降低运维成本为目的的一套电力运维管理系统。综合分析采用智慧物联网、人工智能等现代化经济信息网络技术&#xff0c;配置智能采集终端、小安神童值班机器人或边缘网关&#xff0c;实现对企事业用户供配电系统的数字化远程监控…

Elasticsearch:使用 ELSER 文本扩展进行语义搜索

在今天的文章里&#xff0c;我来详细地介绍如何使用 ELSER 进行文本扩展驱动的语义搜索。 安装 Elasticsearch 及 Kibana 如果你还没有安装好自己的 Elasticsearch 及 Kibana&#xff0c;请参考如下的链接来进行安装&#xff1a; 如何在 Linux&#xff0c;MacOS 及 Windows 上…

Opengl之立方体贴图

简单来说,立方体贴图就是一个包含了6个2D纹理的纹理,每个2D纹理都组成了立方体的一个面:一个有纹理的立方体。你可能会奇怪,这样一个立方体有什么用途呢?为什么要把6张纹理合并到一张纹理中,而不是直接使用6个单独的纹理呢?立方体贴图有一个非常有用的特性,它可以通过一…

【计算机视觉|人脸建模】学习从图像中回归3D面部形状和表情而无需3D监督

本系列博文为深度学习/计算机视觉论文笔记&#xff0c;转载请注明出处 标题&#xff1a;Learning to Regress 3D Face Shape and Expression from an Image without 3D Supervision 链接&#xff1a;[1905.06817] Learning to Regress 3D Face Shape and Expression from an I…