原帖地址:http://www.ibm.com/developerworks/cn/webservices/ws-address.html

Doug Davis, 架構(gòu)師, IBM

2004 年 4 月 01 日

Web 服務(wù)尋址(WS-Addressing)協(xié)議可能與第一眼看上去的的樣子有很大的不同。但是它構(gòu)建的消息信息頭將使新的 Web 服務(wù)消息流模式成為可能——而且它將對 SOAP 引擎以及 SOAP 協(xié)議本身的未來造成深遠(yuǎn)的影響。

大約在一年以前,IBM、BEA 和 Microsoft 推出了一個(gè)稱為 Web 服務(wù)尋址(WS-Addressing)的新規(guī)范(請參閱下面參考資料部 分的相關(guān)鏈接)。在整個(gè) 14 頁里,它僅僅聲明了幫助人們?nèi)绾螛?biāo)準(zhǔn)化指定 Web 服務(wù)的位置的方法。然而,Web 服務(wù)尋址(WS-Addressing)具有從根本上改變 SOAP 處理模型的潛力。但是,究竟是怎樣改變的呢?而且,更重要的是,為什么要改變呢?為了更好地回答這些問題,讓我們先來研究一下這個(gè)規(guī)范本身究竟說了些什 么。(應(yīng)該注意的是,這里的討論將并不探討這個(gè)規(guī)范的實(shí)際實(shí)現(xiàn)的細(xì)節(jié);相反,我將討論為什么它在 SOAP 中的角色將來會那么關(guān)鍵。)

如果您正確地了解了事實(shí),那么在所有多余的話之后,Web 服務(wù)尋址(WS-Addressing)實(shí)際上只包括兩個(gè)新概念:端點(diǎn)引用(endpoint reference,EPR)和 SOAP 結(jié)構(gòu)的消息信息(message information,MI)頭。

端點(diǎn)引用(Endpoint reference)

在 Web 服務(wù)尋址(WS-Addressing)出現(xiàn)以前,為了找到一個(gè) Web 服務(wù)的位置,您不得不請求端點(diǎn)的 URL 或求助于 Web 服務(wù)描述語言(WSDL)。這聽起來好像夠簡單了,那么您為什么還需要 Web 服務(wù)尋址(WS-Addressing)呢?隨著 Web 服務(wù)的發(fā)展,很自然,它們將開始變得復(fù)雜,以便支持企業(yè)級的解決方案。例如,可能需要在 SOAP 請求中包含附加信息來幫助惟一地識別您正在與之對話的 Web 服務(wù)實(shí)例。這將與在請求中包含會話標(biāo)識符或?qū)嵗?ID 相類似。這么做并不是非常的重要。

然而,使用會話標(biāo)識符(通過將某些像 resourceID=123 這樣的信息附加到 URL)并不完全類似于 SOAP。SOAP 純粹主義者可能更愿意回到 SOAP 中定義的可擴(kuò)展性模型,并使用附加的 SOAP 頭包含這個(gè)新的信息來處理消息;例如:

<widget:resourceID>123</widget:resourceID>

從技術(shù)上來說,兩種方法中的任何一種 ——改變請求的 URL 或在 SOAP 頭中包含識別信息——都可以很好地滿足這些目的。然而,如果您使用 SOAP 頭而不是在 URL 中編碼這個(gè)附加信息,那么您將不再綁定于一個(gè)特定的傳輸協(xié)議。想象這樣一種情況,一個(gè) SOAP 消息為了到達(dá)它的最終目的地實(shí)際上通過了多個(gè)傳輸協(xié)議。如果兩個(gè)傳輸協(xié)議都是 HTTP,那么就可以很容易地重用 URL 的查詢字符串部分。但是其他的傳輸協(xié)議怎么辦呢,比如 SMTP?resourceID=123 是去哪?它可能變成 SMTP 頭嗎?如果傳輸不支持用戶定義的字段怎么辦?或者,即使它支持,SOAP 消息的最終接收方(SOAP 引擎)將如何知道怎樣向 Web 服務(wù)傳送這些用戶定義的字段呢?

URL 編碼的另外一個(gè)問題是,現(xiàn)在它將特定于 Web 服務(wù)的數(shù)據(jù)緊密地綁定到傳輸——換句話說,現(xiàn)在特定于 Web 服務(wù)的數(shù)據(jù)在 SOAP 信封以外,處于傳輸層。

那么,Web 服務(wù)尋址(WS-Addressing)有什么用處呢?它定義了稱為端點(diǎn)引用(endpoint reference,EPR)的東西。在它最簡單的形式中,EPR 只不過就是由一些 XML 元素包裝的 URL。清單 1 給出了一個(gè)示例。

清單 1. 一個(gè)簡單的端點(diǎn)引用(EPR)
  <widget:myLocation>
<wsa:Address>http://localhost/WidgetService</wsa:Address>
</widget:myLocation>

這里,widget:myLocation 是端點(diǎn)引用(EPR),在它的內(nèi)部是一個(gè) Web 服務(wù)尋址的(WS-Addressing-defined)定義的元素,稱為 wsa:Address (當(dāng)試圖與 WidgetService 對話時(shí),使用它來指定 URL)。

清單 2 添加了附加資源 ID 信息。

清單 2. 帶有添加的 ReferenceProperties 元素的端點(diǎn)引用(EPR)
  <widget:myLocation>
<wsa:Address>http://localhost/WidgetService</wsa:Address>
<wsa:ReferenceProperties>
<widget:resourceID>123</widget:resourceID>
</wsa:ReferenceProperties>
</widget:myLocation>

這夠容易了:您可以添加一個(gè)稱為 ReferenceProperties 的新 XML 元素,并且在它的內(nèi)部有一個(gè)包含特定于您的 Web 服務(wù)的數(shù)據(jù)的元素,稱為 resourceID (也稱為引用特性(reference property))。這個(gè) ReferenceProperties 元素可以封裝所有特定于 Web 服務(wù)的數(shù)據(jù)。但是現(xiàn)在您將如何處理這個(gè) XML 塊呢?因?yàn)槟谑褂?resourceID,那就繼續(xù)使用它,并且假定您之所以使用這個(gè)附加信息是因?yàn)榇嬖谟?WidgetService 使用的多個(gè) Widget 實(shí)例。您可以設(shè)想,在某種程度上,您或者創(chuàng)建了一個(gè)實(shí)例,或者請求服務(wù)返回一個(gè)指向?qū)嵗闹羔槨<俣埱罅送ㄟ^調(diào)用某個(gè) createWidget() 操作來創(chuàng)建的一個(gè)新的實(shí)例。但是,WidgetService 是怎樣返回到這個(gè)新的 widget 的引用的呢?正如您可能已經(jīng)猜到的,它是通過返回一個(gè)端點(diǎn)引用(EPR)來實(shí)現(xiàn)的,如清單 3 所示。

清單 3. 使用端點(diǎn)引用(EPR)來返回引用
  <soap:Envelope...>
<soap:Body>
<widget:createWidgetResponse...>
<widget:widgetReference>
<wsa:Address>http://host/WidgetService</wsa:Address>
<wsa:ReferenceProperty>
<widget:resourceID>123</widget:resourceID>
</wsa:ReferenceProperty>
</widget:widgetReference>
</widget:createWidgetResponse>
</soap:Body>
</soap:Envelope>

在這里,widgetReference 是一個(gè)端點(diǎn)引用(EPR)。Web 服務(wù)尋址(WS-Addressing)規(guī)范要求 Address 元素,但是 resourceID 是特定于 WidgetService 的。

您 可能一邊看這個(gè)例子,一邊納悶,為什么您不是僅僅返回字符串“123“,而是返回整個(gè)端點(diǎn)引用(EPR)——為什么您需要增加額外的復(fù)雜性?實(shí)際上,有幾 個(gè)原因說明了為什么額外的抽象實(shí)際上最后會使工作更容易。首先,消息的接收方不需要知道端點(diǎn)引用(EPR)的任何內(nèi)容。如果您返回像“123”這么簡單的 信息,那么接收方將不得不既要知道這是一個(gè)字符串,而且還要知道這個(gè)字符串的含義以及稍后應(yīng)該如何使用這個(gè)字符串。潛在地,接收方可能被要求有區(qū)別地解釋 返回值,這取決于它正在對話的應(yīng)用程序的類型。通過使用端點(diǎn)引用(EPR),您已經(jīng)使 Web 服務(wù)的引用的格式標(biāo)準(zhǔn)化,更確切地說,也使 Web 服務(wù)的實(shí)例的引用的格式標(biāo)準(zhǔn)化了。

端點(diǎn)引用(EPR)的另外一個(gè)重要方面是必需的元素:Address。因?yàn)槎它c(diǎn)引用(EPR)具有這個(gè) Address 字段,所以這個(gè)字段可以包含與原始請求的 URL 完全不同的 URL。例如,createWidget() 調(diào)用的 URL 可能以 .../createWidgetService 結(jié)束,而隨后服務(wù)調(diào)用的 URL 可能是 .../WidgetService。不必理會特定的值,關(guān)鍵是這個(gè)端點(diǎn)引用(EPR)的接收方不需要知道任何關(guān)于如何解釋數(shù)據(jù)的事情;它僅僅需要知道 Address 字段是應(yīng)該用于未來消息的 URL,以及所有的引用特性(reference properties)應(yīng)該都是在那些消息中的 SOAP 頭。所以,對于這個(gè)端點(diǎn)引用(EPR)的未來請求的 SOAP 信封將采用清單 4 中所給出的形式。

清單 4. 用于請求我們的樣本端點(diǎn)引用(EPR)的 SOAP 信封
  <soap:Envelope...>
<soap:Header>
<wsa:To> http://host/WidgetService </wsa:To>
<widget:resourceID>123</widget:resourceID>
</soap:Header>
<soap:Body>
...
</soap:Body>
</soap:Envelope>

這個(gè)信封將被發(fā)送到 http://host/WidgetService(我很快將討論 wsa:To 頭)。現(xiàn)在,WidgetService 順利處理這個(gè) SOAP 消息所需的全部信息都可以在信封中獲得,沒有什么是特定于傳輸協(xié)議的——而且最重要的是,客戶端應(yīng)用程序完全不知道這個(gè)附加信息(消息的接收方需要它(比 如,引用特性)來順利地處理消息)。一般來說,所有的客戶端基礎(chǔ)設(shè)施都需要知道如何處理端點(diǎn)引用(EPR)。

所 以,現(xiàn)在您已經(jīng)將傳送 Web 服務(wù)的引用的方法標(biāo)準(zhǔn)化了。標(biāo)準(zhǔn)化是一件好事,但是到目前為止,您幾乎還沒有看到前面聲稱的 Web 服務(wù)尋址(WS-Addressing)將改變 SOAP 本身所具有的優(yōu)點(diǎn)。在下一部分中,您會對此有更好的理解,接下來我們介紹 Web 服務(wù)尋址(WS-Addressing)的第二個(gè)特征:消息信息(message information,MI)頭。





回頁首


消息信息頭(MI header)

Web 服務(wù)尋址(WS-Addressing)規(guī)范定義了一些附加的(當(dāng)然,也是標(biāo)準(zhǔn)的)SOAP 頭,它們應(yīng)該用于幫助傳送關(guān)于消息的信息。在這一部分中,我將介紹其中比較有趣的一些。

To

To 只不過是目標(biāo) Web 服務(wù)的 URL。一般來說,這個(gè) URL 和 HTTP 請求的 URL 是相同的,但是這并不是必需的。

清單 5. To 頭
      	<wsa:To> http://host/WidgetService </wsa:To>

當(dāng)使用端點(diǎn)引用(EPR)時(shí),To 頭應(yīng)該與 <wsa:Address> 元素具有相同的值——查閱前面的部分中的例子可以獲得更多的細(xì)節(jié)。

From

From 是消息發(fā)送方的端點(diǎn)引用(EPR)。如果消息接收方需要向發(fā)送消息的端點(diǎn)發(fā)送回消息,那么它應(yīng)該使用這個(gè)端點(diǎn)引用(EPR)。請注意,同樣也有一個(gè) ReplyTo 頭,它指示響應(yīng)消息應(yīng)該去往何處。From 頭將用于這樣的情況,如同那些由 WS-ReliableMessage 規(guī)范所管理的,Acknowledgement 需要被發(fā)送回發(fā)送方。清單 6 給出了一個(gè)運(yùn)行的 From 頭示例。

清單 6. From 頭
      <wsa:From> 
<wsa:Address> http://client/myClient </wsa:Address>
</wsa:From>

ReplyTo

正如所提到的,來自于 Web 服務(wù)的任何響應(yīng)都應(yīng)該被發(fā)送給 ReplyTo 端點(diǎn)引用(EPR)。因?yàn)?FromReplyTo 可能是兩個(gè)截然不同的端點(diǎn)引用(EPR),所以消息的發(fā)送方可能并不是想要接收響應(yīng)的端點(diǎn)。我將在稍后討論這里的含義。清單 7 舉例說明了 ReplyTo 頭的使用。

清單 7. ReplyTo 頭
      <wsa:ReplyTo>
<wsa:Address> http://client/myReceiver </wsa:Address>
</wsa:ReplyTo>

FaultTo

如果消息的響應(yīng)是 SOAP 錯(cuò)誤,那么這個(gè)錯(cuò)誤應(yīng)該在 FaultTo 頭中發(fā)送給端點(diǎn)引用(EPR)。清單 8 給出了一個(gè)示例。

清單 8. FaultTo 頭
      <wsa:FaultTo>
<wsa:Address> http://client/FaultCatcher </wsa:Address>
</wsa:FaultTo>

MessageID

MessageID 只不過就是惟一地識別消息的 URI。清單 9 給出了一個(gè)示例。

清單 9. MessageID 頭
	      <wsa:MessageID>uuid:098765</wsa:MessageID>

Action

清單 10 中顯示的 Action 頭是 SOAP HTTP Action 頭在信封中的版本。

清單 10. Action 頭
      <wsa:Action> http://host/widgetOp </wsa:Action>

RelatesTo

RelatesTo 常常用在響應(yīng)消息中,用來指示它與先前知道的消息相關(guān)并且定義這種關(guān)系。Listing 11 給出了一個(gè)示例。

清單 11. RelatesTo 頭
<wsa:RelatesTo RelationshipType="wsa:Response">
uuid:098765
</wsa:RelatesTo>

清單 11 中的 RelatesTo 頭指示,這是先前知道的請求(Request)消息(它的 MessageIDuuid:098765)的響應(yīng)(Response)消息。在異步消息傳遞場景中,這個(gè)信息頭是很關(guān)鍵的——響應(yīng)消息的接收方必須能夠?qū)⑺c原始請求消息相關(guān)聯(lián)。RelatesTo 頭提供了標(biāo)準(zhǔn)機(jī)制來達(dá)到這個(gè)目的。





回頁首


使用信息頭

Web 服務(wù)尋址(WS-Addressing)定義了所有這些要使用的特殊的頭,但是您可能會這樣自問:“誰關(guān)心這些?”最初,您事實(shí)上已經(jīng)添加了一定程度的復(fù) 雜性,似乎直到現(xiàn)在都還沒有用上。對于簡單的請求/響應(yīng) HTTP 消息流,可能是這樣的。然而,一旦您開始使用異步消息流或跨多個(gè)傳輸協(xié)議發(fā)送消息時(shí),這些頭就變得非常重要了。

以一個(gè)簡單的異步消息交換(甚至是在 HTTP 之上)為例,在這里響應(yīng)消息通過一個(gè)新的連接發(fā)送回去。服務(wù)器是如何知道下一個(gè)響應(yīng)消息需要去往何處呢?一個(gè)顯而易見的解決方案就是將返回地址(或者端點(diǎn)引用)作為應(yīng)用程序數(shù)據(jù)的一部分(即,包含在 Body 中)。然而,如果您使用 Web 服務(wù)尋址(WS-Addressing),那么現(xiàn)在您就有一個(gè)標(biāo)準(zhǔn)位置用于這個(gè)數(shù)據(jù):ReplyTo 消息信息頭/端點(diǎn)引用(MI header/EPR)。同樣地,如果您使用的是類似于 Web 服務(wù)可靠消息傳遞(WS-ReliableMessaging)(參閱參考資料)這樣的規(guī)范,那么在這里潛在地有三個(gè)不同的響應(yīng)消息(傳統(tǒng)的 Reply、可能有的 Fault 以及 Acknowledgement),Web 服務(wù)尋址(WS-Addressing)提供了一個(gè)標(biāo)準(zhǔn)機(jī)制,所有的 Web 服務(wù)通過這個(gè)機(jī)制就可以表示這個(gè)信息。當(dāng)這三個(gè)消息可能需要發(fā)送給三個(gè)不同的端點(diǎn)時(shí),這就變得尤為關(guān)鍵。這與實(shí)際信封所采用的方式毫無差別,在實(shí)際信封上 有用于書寫收信人地址、寄信人地址和粘貼郵票的標(biāo)準(zhǔn)位置。標(biāo)準(zhǔn)化是一件好事。





回頁首


匿名 URI

在所有的信息頭(或者包含 Address 元素,或者像 To 頭那樣對自己進(jìn)行尋址)中,您可以使用一個(gè)特殊的匿名 URI:

http://schemas.xmlsoap.org/ws/2003/03/addressing/role/anonymous

當(dāng)您使用這個(gè) URI 時(shí),您就暗示,對于這個(gè)地址并沒有可用的真正端點(diǎn)。這就意味著不能打開到那個(gè)端點(diǎn)的連接。實(shí)際上,這對消息流有一些非常有趣的副作用。例如,讓我們假設(shè)您在 ReplyTo 頭的地址中使用了匿名 URI。這是什么意思呢?明顯地,客戶端不想打開一個(gè)新的連接——它不是一個(gè)真正的 URI。使用匿名 URI 就相當(dāng)于根本不使用 ReplyTo 頭——換句話說,響應(yīng)必須在 HTTP 響應(yīng)消息中流回。

雖然最初您可能覺得這個(gè)例子只是比較有趣地使用 ReplyTo 和匿名 URI,而實(shí)際上,它對于消息處理模型具有非常大的影響。考慮這樣一種情況,它的請求消息類似于清單 12 所示。

清單 12. 使用匿名 URI
  <soap:Envelope...>
<soap:Header>
<wsa:To> http://host/WidgetService </wsa:To>
<wsa:ReplyTo>
<wsa:Address>
http://schemas.xmlsoap.org/ws/2003/03/addressing/role/anonymous
</wsa:Address>
</wsa:ReplyTo>
<wsa:FaultTo>
<wsa:Address>
http://client/myReceiver
</wsa:Address>
</wsa:FaultTo>
...
</soap:Header>
<soap:Body>
...
</soap:Body>
</soap:Envelope>

注意,這個(gè)消息的發(fā)送方要求通過 HTTP 響應(yīng)流發(fā)送回響應(yīng)消息(正如在 ReplyTo 頭中匿名 URI 所指示的)。這意味著發(fā)送這個(gè)代碼的客戶端假定同步處理模型,是這樣嗎?有可能。看一下 FaultTo 頭——那是一個(gè)真正的、非匿名的端點(diǎn)。所以,如果這個(gè)消息的接收方產(chǎn)生一個(gè) SOAP 錯(cuò)誤,那么應(yīng)該將那個(gè)錯(cuò)誤發(fā)送到 http://client/myReceiver, 而且不通過 HTTP 響應(yīng)流——那是一個(gè)異步處理模型。考慮它真正的意思是什么:在某些情況中,客戶端不能控制消息的傳回是同步地,還是異步地。這可能會對 SOAP 引擎造成非常大的影響。它們不再能夠假定每次調(diào)用一個(gè)處理模型——它們必須能夠基于從服務(wù)器取回的信息來在兩者之間轉(zhuǎn)換。所以,在這種情況下,客戶端可能 等待 HTTP 響應(yīng)流上的響應(yīng)。如果沒有得到,那么它將等待異步到達(dá) http://client/myReceiver 端點(diǎn)上的響應(yīng)。這個(gè)動態(tài)的轉(zhuǎn)換可能對于當(dāng)前某些 SOAP 處理器來說并不是一個(gè)簡單的任務(wù)。

當(dāng)然,并不只是客戶端受到了影響。接收方(或服務(wù)器)必須能夠基于各種信息頭中的值和生成的響應(yīng)消息來動態(tài)地在同步模型和異步模型之間轉(zhuǎn)換。

它還有另外一個(gè)有趣的副作用。在大部分服務(wù)中,WSDL 描述的是非常簡單的請求/響應(yīng)同步消息模式。但是對于 Web 服務(wù)尋址(WS-Addressing)來說,任何 Web 服務(wù)(無論是異步地還是同步地)都將簡單地通過正確地使用 Web 服務(wù)尋址(WS-Addressing)頭來隱式地支持異步。這是 SOAP 應(yīng)用程序現(xiàn)在可用的一個(gè)非常強(qiáng)大的工具。某些規(guī)范,比如 WS-Transactions (WS-Coordination 和 WS-AtomicTransaction——請查閱參考資料),特意定義了兩個(gè)不同的端口類型——一個(gè)用于同步消息傳遞模式,一個(gè)用于異步消息傳遞模式。這種差別現(xiàn)在已經(jīng)變得過時(shí)了。

新興技術(shù)工具包(Emerging Technologies Toolkit,ETTK;請參閱 參考資料以 獲得相關(guān)鏈接)包括使用 Web 服務(wù)尋址(WS-Addressing)規(guī)范的相當(dāng)多的演示。特別是,基于 Web 的 WS-ReliableMessaging demo 讓您可以容易地改變 Web 服務(wù)尋址(WS-Addressing)頭來查看消息流是如何改變的。





回頁首


結(jié)束語

支 持 WS-* 規(guī)范最一般的原因是由于它帶給 Web 服務(wù)世界的標(biāo)準(zhǔn)化程度。Web 服務(wù)尋址(WS-Addressing)通過定義端點(diǎn)引用(EPR)和消息信息(MI)頭來明確地達(dá)到這個(gè)目的。這個(gè)定義提供了單一的機(jī)制,通過這一機(jī) 制,人們能夠指定 Web 服務(wù)(或者服務(wù)的實(shí)例)的位置以及服務(wù)在 SOAP 消息中使用那些端點(diǎn)引用(EPR)的方式(通過 MI 頭)。但是,正是在消息處理模型/流中的隱式改變甚至對 SOAP 具有更加重大的影響。Web 服務(wù)尋址(WS-Addressing)的重要性將隨著時(shí)間而增加——以致到達(dá)它將被視為那些規(guī)范中的一個(gè)成員,它本身應(yīng)該是核心 SOAP 規(guī)范的一部分。



參考資料



關(guān)于作者


Doug Davis 是 IBM Software Standards 部門的架構(gòu)師。他以前擔(dān)任過的職務(wù)包括 Emerging Technologies Toolkit、WebSphere Machine Translation、Team Connection 和 IBM Fortran 90 的技術(shù)總監(jiān)。