使用 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 的微服务(一)
【squids.cn】 全网zui低价RDS,免费的迁移工具DBMotion、数据库备份工具DBTwin、SQL开发工具等 Apache Camel 绝非Java企业技术栈领域的新手。它由James Strachan在2007年创建,旨在实现著名的 "EIP 书"(由Gregor Hohpe和Bobby W…...

如何通过高级流量管理提高 Kubernetes 的弹性
原文作者:Jenn Gile - F5 NGINX 产品营销经理 原文链接:如何通过高级流量管理提高 Kubernetes 的弹性 转载来源:NGINX 中文官网 NGINX 唯一中文官方社区 ,尽在 nginx.org.cn 编者按 —— 本文是以下系列博文中的一篇(…...
解决Springboot集成RabbitMQ不自动生成队列的问题
1.RabbitMQ消息的消费端服务 RabbitMQ懒加载模式, 需要配置消费者监听才会创建 RabbitListener(queues "test.queue")另外一种方式(若Mq中无相应名称的队列,会自动创建Queue),改为如下 RabbitListener(queuesToDeclare { Queue(value "test.queu…...
【数据结构】Decreasing String—CF1886C
Decreasing String—CF1886C 代码我现在还不是很理解,群友说是单调栈。 C o d e Code Code #include <bits/stdc.h> #define int long long #define sz(a) ((int)a.size()) #define all(a) a.begin(), a.end() using namespace std; using PII pair<int…...

【广州华锐互动】钢厂铸锻部VR沉浸式实训系统
随着科技的不断进步,虚拟现实(VR)技术已成为当今最具潜力的技术之一。在钢铁行业中,VR虚拟仿真实训已经被广泛应用于培训和教育领域,特别是钢铁厂铸锻部,通过VR技术,可以大大提高培训效率,降低培训成本&…...
Python中执行SQL报错unsupported format character ‘Y‘ (0x59) at index 34
Python中执行SQL报错unsupported format character ‘Y’ (0x59) at index 34 from sqlalchemy import create_engine engine_ts create_engine(mysqlpymysql://root:MySQL123456127.0.0.1:3306/dbmysql?charsetutf8&use_unicode1) sql "select date_format(t.tr…...

云数据库(林子雨慕课课程)
文章目录 6.云数据库6.1 云数据库概述6.2 云数据库产品6.3 UMP系统6.3.1 UMP系统概述6.3.2 UMP系统架构6.3.3 UMP系统功能 6.4 Amazon云数据库6.4.1 Amazon和云计算的渊源6.4.2 Amazon AWS6.4.3 AWS平台上的云数据库6.5 微软云数据库SQL Azure 6.云数据库 6.1 云数据库概述 云…...
2023-10-10 python-从一组颜色中找到与指定颜色最接近的颜色-{K-D树}-记录
摘要: 2023-10-10 python-从一组颜色中找到与指定颜色最接近的颜色-{K-D树}-记录 相关文档: 如何在颜色表中找到与当前颜色最接近的颜色? - 糯米PHP https://zh.wikipedia.org/wiki/%E6%9C%80%E9%82%BB%E8%BF%91%E6%90%9C%E7%B4%A2 https://zh.wikipedia.org/wiki/…...
使用C++实现DNS欺骗攻击
文章为花钱购买转载,但我测试并未成功!!! 使用C实现DNS欺骗攻击-CSDN博客 使用C实现DNS欺骗攻击 DNS劫持是一种常见的网络攻击方式,通过篡改DNS响应数据,使得用户访问的网站被重定向到攻击者指定的恶意站…...
C#WPF属性元素语法应用实例
本文介绍C#WPF属性元素语法应用实例 一、属性元素语法 对于对象元素的某些属性,无法使用特性语法(比如:Background="Blue"),因为无法在特性语法的引号和字符串限制内充分地表达提供属性值所必需的对象或信息。 对于这些情况,可以使用另一个语法,即属性元素语…...
el-select应用虚拟列表,避免过多数据导致浏览器卡死
el-select: element-ui组件中的select下拉选择组件,支持单选、多选等 虚拟列表: 虚拟列表是一种优化技术,用于处理大型列表。在传统的列表中,当用户滚动到底部时,列表会加载所有的数据,这可能导…...
ES6之函数的扩展
函数的扩展 文章目录 函数的扩展1:与解构赋值默认值结合使用2:参数默认值空对象2.1 案例一2.2 案例二2.3 案例三2.4 案例四 3:undefined null参数默认值的区别4:函数length5:作用域5.1 全局变量5.2:局部变量…...

【PPT制作】基础篇
文章目录 一、PPT制作必要的基础设置1.1 自动保存1.2 字体嵌入1.3 撤销步数1.4 图像大小和质量 二、必备快捷键三、设计四原则四、总结 ヾ(๑╹◡╹)ノ" 没有坚持的努力,本质上并没有多大意义ヾ(๑╹◡╹)ノ" 一、PPT制作必要的基础…...

尚硅谷CSS学习笔记
什么是css css(层叠样式表) 它是一种标记语言,用于给HTML结构设置样式。简单理解css可以美化html,实现结构与样式的分离。 <link rel"shortcut icon" href"favicon.ico" type"image/x-icon"&g…...

MYSQL的日志管理
MySQL中有几种类型的日志记录,分别用于记录不同的操作和事件。以下是MySQL中常见的日志类型 错误日志 错误日志是 MySQL 中最重要的日志之一,它记录了当 mysqld 启动和停止时,以及服务器在运行过程中发生任何严重错误时的相关信息。当数据…...

微信小程序在TS模板下引入TDesign组件
介绍 TDesign 是腾讯官方出品的一款微信小程序组件库。本文介绍如何在新建ts空白模板下引入TDesign库 步骤 新建一个空白项目,这里可以选择TS-基础模板 新建项目目录结构如图所示: 注意这里其实小程序的文件都存放在miniprogram文件夹下,…...

alsa pcm接口之pcm设备的状态STATE
应用和库之间的协作: ALSA pcm api设计使用状态来确定应用程序和库之间的通信阶段,实际的状态可以被决定通过使用snd_pcm_state调用,下面列举出来状态: SND_PCM_STATE_OPEN: 表示pcm设备被打开的状态,使用了snd_pcm_open()之后进入该状态,并且让snd_pcm_hw_params()调用失败后,…...

【UE】在游戏运行时,通过选择uasset来生成静态网格体
目录 主要流程 步骤 一、创建用于包含静态网格体的Actor蓝图 二、按钮点击事件 效果 主要流程 用户点击按钮后产生一个文件对话框,用户通过文件对话框选择指定的文件夹,我们获取到这个文件夹路径后处理成“按路径获取资产”节点所需的输入&#x…...

vue中PC端使用高德地图 -- 实现搜索定位、地址标记、弹窗显示定位详情
PC端高德地图使用步骤: 1、注册并登录高德开放平台获取 2、安装高德依赖(amap-jsapi-loader) 3、初始化地图 4、首次打开地图获取当前定位并标记 5、根据已有地址自动定位到指定地址并标记 6、新增、清除标记及自定义信息窗体 7、鼠标点击地…...

服务器数据恢复-DS5300存储raid5硬盘出现坏道离线的数据恢复案例
服务器数据恢复环境: 某单位一台DS5300存储,1个主机4个扩展柜,组建了2组RAID5(一组27块硬盘,一组23块盘)。27块盘的那组RAID5阵列存放Oracle数据库文件,存储系统一共分了11个卷。 服务器故障&a…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...

MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...

ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...

初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)
UniApp 集成腾讯云 IM 富媒体消息全攻略(地理位置/文件) 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型,核心实现方式: 标准消息类型:直接使用 SDK 内置类型(文件、图片等)自…...