使用Mule ESB与Groovy编排RESTful服务【转】很适合我们当前的架构
生活随笔
收集整理的這篇文章主要介紹了
使用Mule ESB与Groovy编排RESTful服务【转】很适合我们当前的架构
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
http://www.infoq.com/cn/articles/restful-services-mule?
在過(guò)去幾年中,REST風(fēng)格的軟件架構(gòu)獲得了越來(lái)越多的認(rèn)可,這主要是因?yàn)樗鼫p少了系統(tǒng)對(duì)動(dòng)件的需求、同時(shí)使系統(tǒng)耦合性更低,彈性更好。?目前越來(lái)越多的REST資源出現(xiàn)在企業(yè)應(yīng)用中,因此對(duì)這些資源進(jìn)行編排就顯得非常重要了。比方說(shuō),典型的業(yè)務(wù)活動(dòng)就包含了資源的創(chuàng)建,然后是資源的查找及其他資源的創(chuàng)建等。?
本質(zhì)上來(lái)說(shuō),與RESTful服務(wù)的交互是相當(dāng)簡(jiǎn)單的:需要構(gòu)造并發(fā)送適當(dāng)?shù)恼?qǐng)求(請(qǐng)求頭和請(qǐng)求體),然后分析返回的響應(yīng)(響應(yīng)頭和響應(yīng)體)。完成這個(gè)處 理并不需要什么特別的工具或是框架,只要有一個(gè)好用的HTTP客戶端程序庫(kù)就足夠了。除此之外,由于RESTful交互過(guò)程中所涉及到的不同實(shí)體是由所謂 的微格式定義的,因此能夠輕松解析或是輸出這些實(shí)體的能力就顯得非常重要了。?
編排與多個(gè)資源的交互是個(gè)棘手的問(wèn)題。我們需要定義編排、處理錯(cuò)誤并不斷嘗試,同時(shí)系統(tǒng)必須能夠在壓力下表現(xiàn)良好。作為一個(gè)集成框架,Mule提供了我們所需的一切。?
來(lái)考慮一個(gè)例子吧,某商業(yè)系統(tǒng)對(duì)新訂單的處理需要如下編排:?
通過(guò)向服務(wù)發(fā)送一個(gè)XML實(shí)體來(lái)創(chuàng)建一個(gè)新訂單。?
尋找新創(chuàng)建的訂單資源并從中提取出確認(rèn)信息。?
根據(jù)確認(rèn)信息并通過(guò)郵件網(wǎng)關(guān)向客戶發(fā)送一條確認(rèn)消息。?
我們將在本文詳細(xì)分析上面每一步的交互過(guò)程,同時(shí)還會(huì)介紹為了獲得上述交互所需的Mule動(dòng)件和Groovy特性。?
總體的編排包含了一系列通過(guò)特定路由、過(guò)濾器以及內(nèi)存消息隊(duì)列(aka VM隊(duì)列)連接起來(lái)的Mule服務(wù)。 最近InfoQ上的這篇文章介紹了Mule中的消息路由,大家不妨移步一觀。?
Mule對(duì)REST的支持?
Mule提供了一種簡(jiǎn)單而又強(qiáng)大的方式與RESfFul服務(wù)交互,那就是Mule RESTPack。?
Mule RESTPack提供了一整套連接器與完整的指南以幫助用戶創(chuàng)建新的RESTful應(yīng)用。在本文撰寫之際,該軟件包提供了三種傳送器,分別基于三種流行的REST框架:Abdera、Jersey及Restlet。這樣我們就可以輕松公開(kāi)新的資源,但如何集成現(xiàn)有的REST資源呢??
好消息是Mule標(biāo)準(zhǔn)的腳本模塊所提供的Groovy支持有助于Mule HTTP傳送器的使用,這樣我們就可以成功與RESTful服務(wù)交互了。?
向Mule發(fā)送POST請(qǐng)求?
首先來(lái)看看第一個(gè)交互。HTTP向特定的資源發(fā)送一個(gè)XML實(shí)體來(lái)創(chuàng)建訂單,如以下程序片段所示:?
POST /orders HTTP 1.1?
...?
Java代碼??
如果成功服務(wù)器的響應(yīng)如下:?
201 Created?
Location: http://acme.com/order/O13579?
...?
<order id='O13579' />?
在Mule中,我們可以通過(guò)一個(gè)簡(jiǎn)單的HTTP輸出端點(diǎn)(outbound endpoint)實(shí)現(xiàn)該交互。注意到交互本身是通過(guò)向訂單創(chuàng)建服務(wù)發(fā)送一個(gè)包含請(qǐng)求值(客戶與產(chǎn)品ID、數(shù)量)的映射而觸發(fā)的。該服務(wù)如下所示:?
Java代碼??
這全是XML,我們來(lái)仔細(xì)分析一下:?
名為OrderCreationQueue的管道(可以是VM隊(duì)列或是JMS隊(duì)列)接收消息。?
接收到的消息被直接傳遞到另一個(gè)路由,該路由會(huì)將HTTP POST的結(jié)果發(fā)送到下一個(gè)服務(wù),該服務(wù)通過(guò)名為OrderCreationResultQueue(異步的VM隊(duì)列)的管道對(duì)調(diào)用結(jié)果進(jìn)行分析。?
通過(guò)標(biāo)準(zhǔn)的輸出端點(diǎn)在Groovy轉(zhuǎn)換器上執(zhí)行該HTTP POST請(qǐng)求:?
請(qǐng)求訂單的微格式是通過(guò)一個(gè)特定的傳送器創(chuàng)建的,下一節(jié)將對(duì)其進(jìn)行詳細(xì)介紹。?
通過(guò)一小段腳本將結(jié)果代碼抽取出來(lái)并與期望值進(jìn)行比對(duì)。進(jìn)行比較的目的在于將后面的服務(wù)與純的HTTP隔離開(kāi)來(lái):我們所創(chuàng)建的boolean類型的屬性O(shè)rderPlaced是獨(dú)立的,其名稱與進(jìn)行的編排密切相關(guān)。?
類似的,在更具上下文含義的OrderResourceLocation名字下復(fù)制Location頭。注意,該頭 有可能丟失(在失敗的情況下),在這種情況下,我們將其值默認(rèn)設(shè)為空字符串以避免將null屬性加到消息中。?
我們使用了一個(gè)對(duì)象——字符串轉(zhuǎn)換器來(lái)“分離”HTTP響應(yīng)(以流的形式返回)。多虧有了這個(gè)轉(zhuǎn)換器,流得到了完全的處理,其內(nèi)容也通過(guò)使用與 HTTP交換相關(guān)的編碼轉(zhuǎn)換為字符串。當(dāng)流關(guān)閉時(shí),HTTP連接得到了釋放;我們不想一直開(kāi)著它,等待后面的服務(wù)從 OrderCreationResultQueue中拿出響應(yīng)消息。?
Groovy MarkupBuilder的好處?
OrderMapToMicroformat轉(zhuǎn)換器完成了服務(wù)中的重頭戲,而它是由Groovy的MarkupBuilder實(shí)現(xiàn)的。MarkupBuilder API提供了一種自然的方式生成兼容于特定微格式的XML實(shí)體:?
Java代碼??
注意map payload中的值是如何用于組裝XML元素的:這里解決了一些不匹配的命名約定(比如將clientId轉(zhuǎn)換為customerId)。?
如你所期望的那樣,該轉(zhuǎn)換器產(chǎn)生了如下輸入:?
Java代碼??
除了正確的內(nèi)容類型外都是訂單的RESTful服務(wù)用于創(chuàng)建新資源所需的內(nèi)容。?
分析?
現(xiàn)在我們來(lái)看一下負(fù)責(zé)異步分析訂單創(chuàng)建結(jié)果并決定是否需要進(jìn)一步進(jìn)行編排的服務(wù):?
Java代碼??
我們使用的選擇性消費(fèi)者(selective consumer)所接收的消息中一定要包含訂單成功處理的頭信息。如果該頭信息為true,那就通過(guò)一個(gè)名為SuccessfulOrderQueue 的內(nèi)存隊(duì)列將該消息路由給第三個(gè)(也是最終的)服務(wù),該服務(wù)會(huì)處理訂單成功創(chuàng)建的消息。注意在這個(gè)例子中我們只是簡(jiǎn)單地將錯(cuò)誤消息以日志的方式記錄下來(lái), 但在實(shí)際應(yīng)用中需要將錯(cuò)誤消息發(fā)送給專門的隊(duì)列以進(jìn)行后續(xù)的分析或是及時(shí)的反饋。?
向Mule發(fā)送GET請(qǐng)求?
組成該編排的最后一個(gè)服務(wù)負(fù)責(zé)HTTP GET處理,它會(huì)獲得新創(chuàng)建的訂單,訂單中包含了額外的值以形成一個(gè)合法的消息供email網(wǎng)關(guān)使用。如下是個(gè)示例交互:?
GET /order/O13579 HTTP 1.1?
200 OK?
Content-Type: application/vnd.acme+xml?
...?
Java代碼??
好消息是Mule的HTTP傳送包含了一個(gè)名為rest-servicecomponent的組件,該組件簡(jiǎn)化了服務(wù)與REST資源的交互。幸好有了這樣一個(gè)組件,我們就無(wú)需將GET操作的結(jié)果發(fā)給隨后的服務(wù)了,相反可以在單獨(dú)的服務(wù)中完成一切。除此以外,它還支持在配置中使用表達(dá)式,這樣就能實(shí)現(xiàn)與動(dòng)態(tài)構(gòu)建的URL之間的連通了。?
Java代碼??
在接收到成功的訂單消息后,該服務(wù)使用REST服務(wù)組件生成一個(gè)HTTP GET請(qǐng)求,并將該請(qǐng)求發(fā)送給此前存儲(chǔ)在OrderResourceLocation屬性(aka heade)中的URL。注意到我們是如何通過(guò)Mule表達(dá)式框架(使用#[...]語(yǔ)法)在組件中注入動(dòng)態(tài)URL的。?
在將GET請(qǐng)求的響應(yīng)發(fā)送給負(fù)責(zé)與email網(wǎng)關(guān)進(jìn)行通信的服務(wù)前,我們對(duì)XML訂單實(shí)體進(jìn)行了兩次轉(zhuǎn)換:?
如上所述,我們“分離”了響應(yīng)實(shí)體。?
使用轉(zhuǎn)換器解析XML實(shí)體并構(gòu)建一個(gè)映射以供接下來(lái)的服務(wù)使用。這一次,又利用到了Groovy的強(qiáng)大功能。?
Groovy's XmlSlurper Happiness?
Groovy的XmlSlurper是解析XML微格式的理想工具,這要?dú)w功于其類似DSL的API。?
如下代碼展示了OrderMicroformatToEmailMap轉(zhuǎn)換器的實(shí)現(xiàn):?
Java代碼??
沒(méi)錯(cuò),就兩行Groovy代碼,我們使用了一個(gè)命名空間感知的XML解析器和一個(gè)map構(gòu)建器。其好處真是讓人難以置信,不過(guò)這就是創(chuàng)建map(email網(wǎng)關(guān)服務(wù)所期望的)所需的全部?jī)?nèi)容。?
最終的REST?
在本文中,我們遵循著一個(gè)事先定義好的編排,新訂單資源的URL是唯一的動(dòng)態(tài)元素。開(kāi)發(fā)者可以利用示例中介紹的轉(zhuǎn)換器和表達(dá)式來(lái)支持更多的動(dòng)態(tài)交互,如果你打算遵從HATEOAS路線,你就能獲得一切。如果事實(shí)如此,那其他的Mule路由就唾手可得了,比如可以創(chuàng)建冪等接收者的 路由。你也看到了Groovy的強(qiáng)大功能和靈巧性加上Mule的通信能力極大地簡(jiǎn)化了與RESTful服務(wù)的交互。Mule的表達(dá)式和少量的Groovy 腳本能夠有效地動(dòng)態(tài)定義Mule配置。除此之外,通過(guò)使用異步的VM隊(duì)列將編排的各個(gè)步驟鏈接起來(lái)可以在最大負(fù)荷下優(yōu)雅地降級(jí),這要?dú)w功于Mule內(nèi)在的SEDA架構(gòu)。?
借助于這些強(qiáng)大的工具,集成REST資源變得非常簡(jiǎn)單了。?
祝你好運(yùn)!?
大家可以從http://dossot.net/datastore/mule-groovy-rest.tar.gz下載完整的配置和相關(guān)的測(cè)試資源,這是一個(gè)獨(dú)立的Maven項(xiàng)目。?
查看英文原文:Orchestrating RESTful Services With Mule ESB And Groovy。?
http://www.infoq.com/articles/restful-services-mule
轉(zhuǎn)載于:https://www.cnblogs.com/yecllsl/archive/2011/03/15/1985061.html
總結(jié)
以上是生活随笔為你收集整理的使用Mule ESB与Groovy编排RESTful服务【转】很适合我们当前的架构的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 隐式返回值
- 下一篇: Requests库网络爬虫实战