隨著Web服務(wù)的應(yīng)用不斷增多,對很多項目來說,只解決異構(gòu)平臺的分布式通信問題已經(jīng)不夠了。盡管互操作性是很多人考慮Web服務(wù)時的首要選擇,但分布式系統(tǒng)還帶來了很多難題使得互操作性不那么容易實現(xiàn)。在下面的文章中,我們將看看如何解決Web服務(wù)中的另一個分布式技術(shù)問題:可靠性。
可靠性一個關(guān)鍵概念,在涉及到金融相關(guān)數(shù)據(jù)時尤其如此。天氣預(yù)報的Web服務(wù)代理信息與提供股票市場定單的Web服務(wù)是不能相提并論的。前者可以忍受網(wǎng)絡(luò)失敗并且接受新的請求而不產(chǎn)生大的影響,而如果后者沒有必要的手段來處理這些問題就會產(chǎn)生嚴(yán)重的后果。基于此,在OASIS的贊助下出現(xiàn)了一個專門處理可靠性問題的Web服務(wù)說明書:WS-Reliability .
與其它Web服務(wù)說明書一樣,WS-Reliability體現(xiàn)出可組合性的特點,它允許你按照需求混合匹配各種SOAP行為。通過這種方式,任何基于SOAP的應(yīng)用都可以獲得該可靠性層的好處,只需簡單地添加SOAP頭信息就能使用WS-Reliability中的任何規(guī)則。例如:
- 保證傳送至少一次——發(fā)送的消息必須傳送到接受端,要么給發(fā)送端一個發(fā)送失敗的說明。
- 刪除重復(fù)信息——最多發(fā)送一次,檢測重復(fù)信息并在接受端刪除。
- 保證消息順序——消息按照順序被發(fā)送
盡管WS-Reliability基于SOAP提供協(xié)議以某種方式傳送有效負(fù)載等可靠數(shù)據(jù),但還是要通過一個高層棧的翻譯或處理來決定是否執(zhí)行一個可靠通信。在WS-Reliability's中,高層棧是指能夠進(jìn)行轉(zhuǎn)化的一種特殊環(huán)境,它可以是ESB或折like PHP/PEAR、 Java/Axis等Web服務(wù)框架。
這說明,就算用WS-Reliability實現(xiàn)的服務(wù)能夠無縫地與其它服務(wù)交互,但唯一使用這些信息,還必須學(xué)習(xí)一個特殊的Web服務(wù)棧。有個例子,Apache Software Foundation創(chuàng)建的名為Sandesha 的WS-Reliability實現(xiàn)被加入了Axis框架中。而Axis框架是該基金會創(chuàng)建的一個Java Web服務(wù)棧。
現(xiàn)在,我們來看看Sandesha如何利用Axis框架創(chuàng)建可靠的Web服務(wù)。我們并不深入到細(xì)節(jié),你可以查閱Sandesha的文檔來看看它是如何加入到Axis架構(gòu)中的。或者好好閱讀Axis文檔,如何你對它不熟悉的話。
我們的情景是一個Web服務(wù)客戶端向一個股票報價系統(tǒng)發(fā)出一個可靠請求。表單1.1顯示了我們的客戶端如何使用Sandesha/Axis。
Listing 1.1
import org.apache.axis.client.Service; import org.apache.axis.client.Call; import org.apache.axis.encoding.XMLType; import org.apache.sandesha.Constants; import org.apache.sandesha.SandeshaContext; import javax.xml.namespace.QName; import javax.xml.rpc.ParameterMode; public class StockQuoteClient { ?? private static String targetURL = "http://acmestockquote.com/axis/services/StockQuote"; ?? public static Double stockQuote(String symbol) { ??????? Double priceObject = new Double(0.0); ?try { ???????? Service service = new Service(); ? Call call = (Call) service.createCall(); ? SandeshaContext ctx = new SandeshaContext(); ???? ctx.initCall(call, targetURL,"urn:wsrm:stockQuotePrice",Constants.ClientProperties.IN_OUT); ?????????????? call.setOperationName(new QName("acmestockquote.com", "stockQuotePrice")); ???????? call.addParameter("Text", XMLType.XSD_STRING, ParameterMode.IN); ???????? call.addParameter("Seq", XMLType.XSD_STRING, ParameterMode.IN); ???????? call.setReturnType(org.apache.axis.encoding.XMLType.XSD_DOUBLE); ????? ctx.setLastMessage(call); ?priceObject = (Double) call.invoke(new Object[]{"StockQuote", symbol}); ??????? ctx.endSequence(); ?} catch (Exception e) { ??????????? e.printStackTrace(); ?} ??????? return priceObject; ?? } ?? ??? public static void main(String[] args) { ??????? StockQuoteClient.stockQuote("SLB"); ?StockQuoteClient.stockQuote("BCA"); ?StockQuoteClient.stockQuote("SNY"); ??? } } |
??????StockQuote方法包括我們的業(yè)務(wù)邏輯。首先,使用了Service和Call類,每個對象實例可以被基于Java Axis的Web服務(wù)客戶端正常使用。在上面的例子中,它們都被保證可靠性的層SandeshaContext使用。
SandeshaContext用來維護(hù)在客戶端和服務(wù)器端之間交互的狀態(tài)。這就是為什么Call方法在ctx.initCall和ctx.endSequence之間被嵌套的原因。而它們正代表了Sandesha啟動和結(jié)束一個可靠的過程。實際上,Call方法產(chǎn)生了一個不能被標(biāo)準(zhǔn)Web服務(wù)操作探測到的錯誤,例如被確保的傳送或者重復(fù)的請求。Sandesha能夠通過它的上下文來決定如何輸出。
在表單中,你還能看到在ctx.initCall方法中有urn:wsrm:stockQuotePrice的命名空間。它代表了被加入到客戶端請求中的額外SOAP頭信息,它能被Web服務(wù)提供者識別用來完成可靠性過程。在Axis/Sandesha的例子中,盡管二者的結(jié)合提供了對構(gòu)建具有翻譯WS-Reliability客戶端能力的服務(wù)提供者的支持,但它還具有本文沒有提到的其它功能。不過,你應(yīng)該注意到Axis/Sandesha框架已經(jīng)與WS-Reliability進(jìn)行了成功的測試,包括不同的Web服務(wù)棧上的客戶端與服務(wù)器端,包括IBM、Microsoft 和Systinet。
至此,我們對Sandesha和WS-Reliability下一個結(jié)論。在解釋了如何利用Web服務(wù)的可靠性特征后,你現(xiàn)在可以考慮實現(xiàn)其它的企業(yè)消息技術(shù),例如至今可靠的分布式通信產(chǎn)品JMS (Java Messaging Service),并且用WS-Reliability提供同樣的可靠性,但要繼承平臺無關(guān)的Web服務(wù)的所有優(yōu)點。