合川網(wǎng)站建設(shè)網(wǎng)絡(luò)營銷前景和現(xiàn)狀分析
【squids.cn】 全網(wǎng)zui低價RDS,免費的遷移工具DBMotion、數(shù)據(jù)庫備份工具DBTwin、SQL開發(fā)工具等
?Apache Camel 絕非Java企業(yè)技術(shù)棧領(lǐng)域的新手。它由James Strachan在2007年創(chuàng)建,旨在實現(xiàn)著名的 "EIP 書"(由Gregor Hohpe和Bobby Woolf編寫,Addison Wesley于2003年10月出版的企業(yè)集成模式)。在2010年初成為最受歡迎的Java集成框架之一后,Apache Camel正處于被歷史所遺忘的邊緣,原因是人們更青睞一種名為企業(yè)服務(wù)總線(ESB)的新架構(gòu)模型,并視其為面向服務(wù)架構(gòu)(SOA)的靈丹妙藥。
然而,在SOA失敗后,Apache Camel(與此同時,已被包括但不限于Progress Software和Red Hat的多家編輯采納,并以商業(yè)名稱如Mediation Router或Fuse進行分發(fā))正在強勢回歸,并且為下一個集成的十年變得更為強大。這種復(fù)出也得益于Quarkus,這是一個新的超音速和次原子Java平臺。
本文旨在提出一種非常便利的微服務(wù)實現(xiàn)方法,使用Apache Camel作為Java開發(fā)工具,Quarkus作為運行時,以及不同的Kubernetes(K8s)集群(從本地的Minikube到像EKS(Elastic Kubernetes Service)、OpenShift或Heroku這樣的PaaS)作為基礎(chǔ)設(shè)施。
項目概述
本項目旨在通過一個簡化的貨幣轉(zhuǎn)賬應(yīng)用程序來闡明相關(guān)觀點,該程序包含四個微服務(wù),具體如下:
aws-camelk-file: 該微服務(wù)輪詢本地文件夾,一旦有XML文件傳入,它就將其存儲在一個新創(chuàng)建的AWS S3 bucket中,該bucket的名稱以mys3開頭,后接一個隨機后綴。?
aws-camelk-s3: 該微服務(wù)監(jiān)聽首個找到的AWS S3 bucket,該bucket的名稱以mys3開頭。一旦有XML文件傳入,它將對文件進行分割、標(biāo)記化和流處理,然后將每個消息發(fā)送到名為myQueue的AWS SQS(簡單隊列服務(wù))隊列。?
aws-camelk-sqs: 該微服務(wù)訂閱名為myQueue的AWS SQS隊列上的消息,并對每個傳入消息執(zhí)行從XML到Java對象的解組操作,然后將其組織為JSON格式,再將其發(fā)送到下面的REST服務(wù)。?
aws-camelk-jaxrs: 該微服務(wù)提供了一個REST API,具有用于創(chuàng)建、讀取、更新和刪除貨幣轉(zhuǎn)賬訂單的端點。它接收/生成JSON輸入/輸出數(shù)據(jù)。它使用一個服務(wù),該服務(wù)展現(xiàn)了由aws-camelk-api模塊定義的接口??赡艽嬖诖私涌诘亩鄠€實現(xiàn),但為簡單起見,在當(dāng)前情況下,我們使用由aws-camelk-provider模塊定義并命名為DefaultMoneyTransferProvider的實現(xiàn),該實現(xiàn)僅在內(nèi)存哈希圖中處理貨幣轉(zhuǎn)賬訂單請求。?
項目的源代碼可以在此處找到。這是一個多模塊的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?
此模塊定義了應(yīng)用程序的域,該域由諸如MoneyTransfer、Bank、BankAddress等業(yè)務(wù)對象組成。集成應(yīng)用的特點之一是其業(yè)務(wù)域是遺留的,通常是幾十年前由忽略了您作為軟件開發(fā)者當(dāng)前正在使用的工具集的業(yè)務(wù)分析師和專家設(shè)計的。這種遺留以各種形式存在,如Excel表格以及CSV或XML文件。
因此,我們在這里考慮了一個典型的情景,根據(jù)該情景,我們的域模型被定義為XML語法,由一對XSD文件定義。這些XSD文件位于src/main/resources/xsd目錄中,并由jaxb2-maven-plugin處理,以生成相關(guān)聯(lián)的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模式編譯器工具,在目標(biāo)包fr.simplex_software.quarkus.camel.integrations.jaxb中基于項目的src/main/resources/xsd目錄中的XSD模式生成Java類。默認(rèn)情況下,這些自動生成的Java對象具有JAXB(Java Architecture for XML Binding)注釋,但沒有構(gòu)造函數(shù),這使得它們有點難以使用,特別是對于必須通過setter實例化的具有許多屬性的類。因此,在上面的列表中,我們將jaxb2-maven-plugin配置為依賴于jaxb3-value-constructor工件。通過這樣做,我們要求xjc編譯器為每個隨后的JAXB處理類生成完整參數(shù)構(gòu)造函數(shù)。
此模塊的最終結(jié)果是一個JAR文件,其中包含我們的領(lǐng)域模型,形式為Java類層次結(jié)構(gòu),所有其他應(yīng)用程序模塊將其用作依賴項。這種方法比手動實現(xiàn)(再次,用Java)由XML語法已經(jīng)定義的域?qū)ο蟮姆椒ǜ鼮閷嵱谩?/p>
模塊 aws-camelk-api?
此模塊非常簡單,因為它僅由一個接口組成。這個接口名為MoneyTransferFacade,是由資金轉(zhuǎn)賬服務(wù)公開的接口。此服務(wù)必須實現(xiàn)公開的接口。實際上,這樣的服務(wù)可能有許多不同的實現(xiàn),具體取決于資金轉(zhuǎn)移的性質(zhì)、銀行、客戶類型以及許多其他可能的條件。在我們的例子中,我們只考慮了該接口的簡單實現(xiàn),如下一節(jié)所示。
模塊 aws-camelk-provider?
此模塊為MoneyTransferFacade接口定義了服務(wù)提供商。在這里使用的SPI(Software Provider Interface,軟件提供商接口)模式是非常強大的,它允許將服務(wù)接口與其實現(xiàn)解耦。
我們對MoneyTransferFacade接口的實現(xiàn)是DefaultMoneyTransferProvider類,它也非常簡單,因為它只是在內(nèi)存哈希映射中創(chuàng)建、讀取、更新和刪除資金轉(zhuǎn)賬訂單。
模塊 aws-camelk-jaxrs?
與僅僅是通用類庫的前面幾個模塊不同,此模塊和接下來的模塊是Quarkus可運行服務(wù)。這意味著它們使用quarkus-maven-plugin來創(chuàng)建一個可執(zhí)行的JAR。
如其名稱所示,此模塊公開了一個JAX-RS(Java API for RESTful Web Services)API來處理資金轉(zhuǎn)賬訂單。Quarkus帶有RESTeasy,這是Red Hat對JAX-RS規(guī)范的完全實現(xiàn),這就是我們在這里使用的。
就MoneyTransferResource類而言,沒有什么特別的要提及的,該類實現(xiàn)了REST API。它提供了創(chuàng)建、讀取、更新和刪除資金轉(zhuǎn)賬訂單的端點,并且額外提供了兩個端點,目的是檢查應(yīng)用程序的活動狀態(tài)和準(zhǔn)備狀態(tài)。
模塊 aws-camelk-file?
此模塊是Camel管道中的第一個模塊,由此模塊將包含資金轉(zhuǎn)賬訂單的XML文件從其初始登陸目錄傳送到REST API,該API代表服務(wù)提供商處理它們。它使用Camel Java DSL(Domain Specific Language,領(lǐng)域特定語言)來執(zhí)行此操作,如下面的列表所示:
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擴展名的文件)的存在。一旦這樣的文件落在給定的目錄中,它將根據(jù)src/main/resources/xsd/money-transfers.xsd文件中定義的模式進行驗證。如果驗證有效,它將被存儲在一個AWS S3存儲桶中,其名稱被計算為等于外部定義的常量,后跟一個隨機后綴。所有內(nèi)容都封裝在一個try...catch結(jié)構(gòu)中,以一致地處理異常情況。
在這里,為了定義外部屬性,我們使用由Quarkus實現(xiàn)的Eclipse MP配置規(guī)范(以及其他規(guī)范),如下面的列表所示:
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存儲桶需要具有跨區(qū)域唯一的名稱,因此,我們需要這樣的隨機后綴來保證唯一性。
模塊aws-camelk-s3
該模塊實現(xiàn)了一個 Camel 路由,每當(dāng)文件到達專用 S3 存儲桶時,AWS 基礎(chǔ)設(shè)施就會觸發(fā)該路由。這是代碼:
from(aws2S3(s3BucketName).useDefaultCredentialsProvider(true))
.split().tokenizeXML("moneyTransfer").streaming()
.to(aws2Sqs(queueName).autoCreateQueue(true).useDefaultCredentialsProvider(true));
一旦觸發(fā),Camel 路由會在對輸入 XML 文件進行標(biāo)記后按順序?qū)ζ溥M行拆分。這個想法是,輸入文件可能包含多個匯款訂單,并且這些訂單將被單獨處理。queueName因此,從此標(biāo)記化和拆分過程發(fā)出的每個匯款訂單都會發(fā)送到 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 消息都包含一個匯款訂單,它在相應(yīng)的MoneyTransferJava 類實例中被解組。然后,一旦解組,每個MoneyTransferJava 類實例就會再次編組到 JSON 有效負(fù)載中。這是必需的,因為我們的 REST 接口使用 JSON 有效負(fù)載,并且與能夠自動執(zhí)行從 Java 對象到 JSON 的轉(zhuǎn)換的標(biāo)準(zhǔn) JAX-RS 客戶端相反,http()這里使用的 Camel 組件不是。因此,我們需要手動完成。通過將交換的標(biāo)頭設(shè)置為 POST 常量,我們設(shè)置將發(fā)送到 REST API 的 HTTP 請求的類型。最后但并非最不重要的一點是,端點 URI 像往常一樣從文件中作為外部定義的屬性注入application.properties。
單元測試
在部署和運行微服務(wù)之前,我們需要對它們進行單元測試。該項目包括幾乎所有模塊的幾個單元測試 - 從aws-camelk-model測試域模型,以及從/到 XML/Java 的各種轉(zhuǎn)換,到aws-camelk-jaxrs,這是我們的終點微服務(wù)。運行單元測試很簡單。只需執(zhí)行:
$ 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. 為了使單元測試按預(yù)期運行,需要一個 AWS 帳戶,并且應(yīng)在本地機器上安裝和配置 AWS CLI。這意味著該文件除其他外還~/.aws/credentials包含您的aws_access_key_id和aws_secret_access_key properties及其關(guān)聯(lián)值。
原因是單元測試使用AWS SDK(軟件開發(fā)工具包)來處理S3存儲桶和SQS隊列,這使得它們不完全是單元測試,而是單元測試和集成測試的組合。
部署和運行
現(xiàn)在,要部署和運行我們的微服務(wù),我們需要考慮許多不同的情景 - 從簡單的本地獨立執(zhí)行到像OpenShift或EKS這樣的PaaS部署,再到像Minikube這樣的本地K8s集群。因此,為了避免在這里產(chǎn)生一些混淆,我們更傾向于為每種部署情景單獨撰寫一篇文章。
所以請關(guān)注下一篇文章。
作者:Nicolas Duminil
更多內(nèi)容請關(guān)注公號【云原生數(shù)據(jù)庫】
squids.cn,云數(shù)據(jù)庫RDS,遷移工具DBMotion,云備份DBTwin等數(shù)據(jù)庫生態(tài)工具。