使用 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…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
