發(fā)布于:2021-01-16 14:11:16
0
1749
0
自2007年由Apache社區(qū)創(chuàng)建以來,開源集成框架apachecamel已經(jīng)成為開發(fā)人員的最愛。它被認(rèn)為是設(shè)計SOA/集成項目和處理復(fù)雜的企業(yè)集成用例的關(guān)鍵技術(shù)。本文是本系列文章的第一部分,它將揭示框架如何從特定領(lǐng)域的語言生成交換發(fā)生的路徑,如何根據(jù)所選的模式進(jìn)行處理,以及最終如何進(jìn)行集成。
簡介
從一般的觀點來看,設(shè)計集成體系結(jié)構(gòu)并不是一項顯而易見的任務(wù),即使您想要使用的技術(shù)和框架相對容易理解和實現(xiàn)。困難在于消息的數(shù)量、要應(yīng)用的轉(zhuǎn)換、交換的同步性或異步性、順序或并行運(yùn)行的進(jìn)程,當(dāng)然還有對在多個jvm中運(yùn)行的此類項目的監(jiān)視。
在傳統(tǒng)的Java應(yīng)用程序中,我們從類調(diào)用方法,同時傳遞和/或返回對象。被調(diào)用的方法是鏈?zhǔn)降?,對象傳輸信息,有時在事務(wù)中登記,但總是部署在同一個Java容器中(Web、JEE、Standalone)。除非我們必須調(diào)用外部系統(tǒng)或集成遺留應(yīng)用程序、RDBMS等,否則大多數(shù)調(diào)用都是本地同步完成的。
如果一個服務(wù)想要可重用,它需要被打包,在庫中進(jìn)行版本控制,并與將使用它的項目通信。這種方法適用于由內(nèi)部開發(fā)團(tuán)隊維護(hù)的項目,在這些項目中,成本可以由IT部門支持,但它會遇到不同的問題,并且大多數(shù)情況下要求我們使用相同的編程語言或特定技術(shù)來互連流程(RPC、IIOP等),即部署代碼的容器。
圖1:SOA
為了允許應(yīng)用程序在沒有此類約束的情況下獨(dú)立開發(fā),必須在負(fù)責(zé)使用它的服務(wù)的請求/消息的發(fā)布者之間促進(jìn)解耦。這種新的體系結(jié)構(gòu)范例稱為面向服務(wù)的體系結(jié)構(gòu),它使用傳輸層在系統(tǒng)之間交換信息。SOA的一個直接好處是促進(jìn)基于契約的方法來定義應(yīng)用程序之間公開的服務(wù),并根據(jù)“治理規(guī)則”來管理它們。
SOA方法已經(jīng)能夠聯(lián)合不同的團(tuán)隊,解決圍繞更復(fù)雜項目開發(fā)的問題。這種IT轉(zhuǎn)型是必需的,因為公司需要更靈活地適應(yīng)市場需求,信息必須實時提供,業(yè)務(wù)適應(yīng)需要現(xiàn)有的遺留系統(tǒng)和后臺系統(tǒng)的支持。
雖然SOA理念已被廣泛采用,但掌握XML、XDS模式、Web服務(wù)和業(yè)務(wù)流程引擎的學(xué)習(xí)曲線、橫向團(tuán)隊的創(chuàng)建和管理,管理服務(wù)所需的治理和所需的技能無疑是解釋SOA為何仍難以被公司采用的因素。此外,資訊科技部門不僅關(guān)心推廣和管理網(wǎng)頁服務(wù)和注冊處,而且也關(guān)心不同系統(tǒng)之間的互聯(lián)、交換、轉(zhuǎn)換和驗證資訊。在闡述SOA原則時,IT工作的這個集成方面被完全“低估”了。
企業(yè)集成模式
2005年,Gregory Hope和Bobby Wolf出版了一本名為《企業(yè)集成模式》的書,他們不僅花時間描述復(fù)雜的用例,還定義了詞匯表、語法和設(shè)計圖標(biāo)來表達(dá)IT部門必須解決的復(fù)雜集成模式。這本書改變了開發(fā)團(tuán)隊(業(yè)務(wù)/功能分析人員、數(shù)據(jù)建模人員和開發(fā)人員)協(xié)作設(shè)計集成/SOA項目的方式。討論的重點不僅僅是服務(wù)、XML的結(jié)構(gòu)和業(yè)務(wù)流程的設(shè)想,還包括如何使用模式來解決集成用例(聚合、拆分、過濾、基于內(nèi)容的路由、動態(tài)路由)。這本書利用參與者來實現(xiàn)更靈活的編程方法。為了支持本書中描述的EIP并幫助開發(fā)人員解決集成用例,apachecamel集成Java框架創(chuàng)建于5年前。
EIP設(shè)計圖標(biāo)
發(fā)現(xiàn)Apache
表示聚合或路由的EIP模式,這要求我們使用語言“表示”它們。這種語言不是一種新的編程語言,而且是一種特定于某個領(lǐng)域的語言,它充分地描述了所選領(lǐng)域(集成)的問題。apachecamel是一個Java集成框架,它支持omainSspecificLanguage(aka)。DSL;有關(guān)更多信息,請參閱Camel文檔)使用面向?qū)ο蟮恼Z言,如Java、Scala、Groovy等。不需要解析器、編譯器或解釋器,而是命令列表、按順序排列的指令:
instruction1().instruction2()....instructionN();
apachecamel也被定義為“中介和路由”引擎。讓我們想想全球道路網(wǎng):我們可以在城市和首都之間運(yùn)輸不同類型和大小的車輛,運(yùn)送不同出身、膚色、年齡、性別的乘客。根據(jù)交通狀況,可以調(diào)整行程,使用替代道路。同樣,Apache Camel沿著路徑傳輸消息。
from("Brussels") .to("Paris"); // Transport passengers from Brussels Capital to Paris
每個Camel路由都以from指令開始,這一指令特別重要,因為它充當(dāng)使用者,并根據(jù)它是被觸發(fā)(“事件驅(qū)動體系結(jié)構(gòu)”)還是能夠定期讀取數(shù)據(jù)(“輪詢體系結(jié)構(gòu)”)發(fā)揮特定的作用。使用者是一個工廠,每當(dāng)接收到數(shù)據(jù)時,就會通過Apache Camel路由創(chuàng)建和傳輸“消息”。
當(dāng)然,apachecamel根本不在路線上運(yùn)輸“乘客”,而是運(yùn)輸“信息”。這些消息將通過一系列步驟,即處理器來轉(zhuǎn)換、驗證、格式化、豐富所接收信息的內(nèi)容。該框架提供了不同的處理器,這些處理器經(jīng)過專門化(Bean、Log),以簡化我們希望應(yīng)用的操作,如下面的代碼:
from("Brussels") .bean("Border","validPassport") .log("Passport has been controlled") .bean("Border","controlTicket") .to("log:travel://LogLevel=INFO" + "Ticket has been controlled") .to("Paris");
放置在“from”后面的每個處理器傳遞信息,并像火車車廂一樣“形成”一條鏈,如下圖所示:
from("") ... .to("log:travel://LogLevel=INFO" + "Ticket has been controlled") // .to("file:///outputDirectoryWhereFileWillbeCreated") // .to("http://www.google.be?doASearch") // Call External HTTP Server .to("jms://queue:outputQueue; // Response received is published in a queue
然而,某些處理器會產(chǎn)生一條消息,Camel會將該消息發(fā)送到服務(wù)器(SMTP、FTP)、應(yīng)用程序(RDBMS)、代理(JMS)和另一個Camel路由(DIRECT、SEDA、VM),并且在某些情況下會等到收到響應(yīng)(HTTP、TCP/IP、WS、REST、WebSocket)。
Camel的一個關(guān)鍵好處是,它提供了根據(jù)它所攜帶的信息(使用消息結(jié)構(gòu))做出決策的可能性。這樣一個與對象交換相對應(yīng)的消息包含了主體中攜帶的信息或?qū)ο螅舶祟^的元數(shù)據(jù)部分。
元數(shù)據(jù)允許您記錄傳輸?shù)膶ο?,但也可以知道它們來自何處、它們的來源(文件、Ftp、WebService、SMTP、JDBC、JPA、JMS等)以及它們應(yīng)該去哪里。為了支持決策,Camel使用一種EIP模式,即基于內(nèi)容的路由器、過濾器、聚合器、拆分器……以及一種稱為表達(dá)式語言(Simple、Constant、Xpath、Xquery、SQL、Bean、Header、Body、OGNL、Mvel、EL……)的特定語言。
這些決定是由謂詞做出的,我們可以將這些謂詞與If/Then/Else、While/For語句進(jìn)行比較。路由引擎將決定如何處理“消息”以及它們應(yīng)該去哪里。
如果滿足條件,基于內(nèi)容的路由器使用的選項/時間將計算(使用謂詞和表達(dá)式語言)。如果是這種情況,則將交換移動到分支路徑中定義的處理器,否則它們將移動到另一個管道中。所有這些都體現(xiàn)在以下方面:
// from("Brussels") .bean("Border","validPassport") .choice() .when() .simple(${header.isValid}==true) // Simple language checks if the status is equal to true .log("Passenger has been controlled") .log("We can now control their ticket") .bean("Border","controlTicket") .to("Paris") .otherwise() .log("Your are not authorized to continue your trip");
對于所使用的某些組件,預(yù)期接收方(HTTP、WebService、REST、JMS–Request/Reply、TCP/IP等)或發(fā)出消息的發(fā)送方會發(fā)出響應(yīng)。在這種情況下,Camel將調(diào)整用于內(nèi)部傳輸消息的模式。此模式通常為InOnly類型,但當(dāng)需要響應(yīng)時,將使用InOut模式。為了傳輸信息并避免將傳入消息與傳出消息混合,Apache Camel將為此目的使用兩個不同的對象,即in或out。當(dāng)不需要響應(yīng)時,即我們舉例來說,如果使用一個文件組件,那么out對象總是空的。
更進(jìn)一步
由于流量由運(yùn)營商控制,apachecamel提供了一個管理路由的環(huán)境(啟動/停止/暫停/恢復(fù)路由中的流量)。這種環(huán)境被稱為容器,或者更準(zhǔn)確地說是上下文。
容器不僅是部署路由的運(yùn)行時,而且充當(dāng)復(fù)雜的生態(tài)系統(tǒng)。它可以跟蹤交換,如何使用框架公開的JMX信息進(jìn)行管理,如何處理線程池,如何發(fā)現(xiàn)路由,如何關(guān)閉路由并生成創(chuàng)建交換時使用的唯一標(biāo)識符。
CamelContext還將注冊使用或生成該信息所需的組件。根據(jù)URI中包含的方案名稱,Apache Camel將掃描classloader加載的類,以找到它想要使用的組件:
"scheme://properties?key1=val2&key2=val3 // "?le:///home/user/integration? " "timer://myTimer?delay=2s&period=10S"
Component類是一個工廠,它將根據(jù)從URI收集的參數(shù)創(chuàng)建一個Endpoint對象(?)?鍵1=值1和鍵1=值2。此對象包含根據(jù)組件扮演的角色創(chuàng)建生產(chǎn)者或使用者所需的方法。
通常,輪詢消費(fèi)者定期掃描文件系統(tǒng)的目錄,讓JMS的偵聽器讀取JMS消息,并將創(chuàng)建一個交換,它將傳播到下一個處理器,如下所示:
@Override protected int poll() throws Exception { Exchange exchange = endpoint.createExchange(); // create a message body Date now = new Date(); exchange.getIn().setBody("Hello World! The time is " + now); try { // send message to next processor in the route getProcessor().process(exchange); return 1; // number of messages polled } }
在另一端,生產(chǎn)者將等待,直到它從處理器得到一個駝峰交換,然后將操縱“消息”,豐富它并更改“元數(shù)據(jù)”:
public void process(Exchange exchange) throws Exception { // Add a new property exchange.getIn().setHeader("FrequentFlyer","true); }
Camel項目通常由一個Java主類組成,我們將在其中創(chuàng)建一個DefaultCamelContext,注冊Camel路由并啟動容器。如以下示例所述,RouteBuilder類是必需的,它的Configure方法調(diào)用靜態(tài)方法(=指令)來設(shè)計駝峰路由(=處理器集合)。路由生成器允許創(chuàng)建一到多條駝峰路由:
// public class MainApp { public static void main(String[] args) throws Exception { // CamelContext = container where we will register the routes DefaultCamelContext camelContext = new DefaultCamelContext(); // RouteBuilder = Where we design the Routes using here Java DSL RouteBuilder routeBuilder = new RouteBuilder() { @Override public void configure() throws Exception { from(?file:///travelers“) .bean(“Flight”,”TransportPassenger”) .to(?file:///authorizedTravelers“); } }; // Add the routes to the container camelContext.addRoutes(routeBuilder); // Start the container camelContext.start(); // When work is done we shutdown it camelContext.stop();
與其他集成框架相比,apachecamel是獨(dú)一無二的,因為它能夠處理Java對象,并且能夠自動將對象類型轉(zhuǎn)換為處理器或謂詞所期望的類型。
在創(chuàng)建CamelContext的過程中,負(fù)責(zé)進(jìn)行類型轉(zhuǎn)換的所有類(文件到字符串、讀取器、字符串到DOM等等)都將加載到一個內(nèi)部注冊表中,Camel處理器在交換處理過程中會查詢到該注冊表。這些轉(zhuǎn)換類來自不同的jar,這是java類路徑的一部分。雖然apachecamel默認(rèn)情況下完成了這樣一個過程,但是您也可以使用特定的指令來指示應(yīng)該將哪個特定的轉(zhuǎn)換器應(yīng)用于接收的對象類型。見下表:
// from("?le:///travelers") // The File endpoint polls every 1s second ?les // available under "travelers" directory .convertBodyTo("String") // We convert Camel Generic File object to a String // which is required by Xpath expression language during Content Based Routing .choice() .when() .xpath("/traveler/@controlled" = 'true') // Check if condition is // matched using as expression left hand side part and condition, right hand side .log("Passenger has been controlled") .to("?le:///authorizedTravelers") .otherwise() .log("Your are not authorized to continue your trip");
下一次
在apachecamel文章的第一部分中,我們介紹了這個Java集成框架的一些基本功能,實現(xiàn)了企業(yè)集成模式,該模式使用特定于領(lǐng)域的語言來設(shè)計在系統(tǒng)/應(yīng)用程序之間傳輸消息的路由。
DSL允許我們定義按順序讀取的指令。當(dāng)Camel組件接收或使用信息時,將創(chuàng)建一個交換,并將其移動到一個處理器集合中,這些處理器對鏈接到Body對象的消息的內(nèi)容進(jìn)行轉(zhuǎn)換。該框架能夠使用支持的一種表達(dá)式語言(Xpath、Simple、SQL、Header、Body、Constant、EL、JavaScript等)和允許我們定義條件的謂詞做出決策(基于內(nèi)容的路由器、過濾器等)。在交換的傳輸過程中,Camel將使用包含轉(zhuǎn)換策略的內(nèi)部注冊表自動將對象從和/或轉(zhuǎn)換為特定類型。Camel項目通常使用一個稱為CamelContext的容器來注冊Camel路由、端點。在本系列的第二部分中,我們將介紹Camel更高級的特性(復(fù)雜數(shù)據(jù)格式的轉(zhuǎn)換、多線程、異步交換等)。