柴曉路 Chief System Architect 2001 年 10 月
本文應SOAP/1.2規范推出的技術背景,就運用SOAP Header擴展SOAP的功能展開討論。當具體的應用中運用了一些與應用本身關聯不是太大而更面向底層控制的服務的時候應當采用SOAP Header來傳輸這些控制信息,理由是這些服務往往是平臺的功能而非具體應用所要實現的功能。從體系架構的觀點來看,解析SOAP Header的就可以由平臺模塊來完成,通過插入不同的標準化的SOAP Header條目解析模塊來完成不同目的的控制功能。而相應的,解析SOAP Body是由應用模塊來完成。這樣在開發和部署上將會非常地清晰。
W3C XML Protocol工作組在今年7月發布了SOAP Version 1.2 Working Draft (SOAP規范1.2版草案,網址是" http://www.w3.org/TR/2001/WD-soap12-20010709/")。同時在2001年4月,在美國的San Jose召開的Web服務研討會上正式確立了SOAP作為Web服務的核心規范的地位。
在SOAP/1.2版中,對于如何拓展SOAP的能力作了明確的指示性的描述,那就是SOAP Body關注于調用本身(基本沒有變化),而SOAP Header從先前的可以由SOAP中介結點處理的模糊指示轉變為SOAP Header是擴展SOAP功能的最佳途徑的明確性指示。
我們知道,SOAP的應用已經有了一定的階段,各種基于SOAP調用的Web服務紛紛出現。然而,目前的應用模式基本上停留在遠程過程/對象的調用上,基于多次協調調用或者遵循上下文的調用模式尚很少使用,這其實是受簡單的SOAP消息的制約。如果擴展,而且是遵循標準的擴展SOAP消息以滿足更復雜情況下的應用成為了目前的一個發展趨勢。
更新的SOAP概念
在討論運用SOAP Header來擴展SOAP功能之前,我們先來看看SOAP/1.2中更新的一些SOAP的基本概念,這些是理解后面的內容的基礎。
SOAP結點 (SOAP Node)
SOAP結點根據SOAP定義的整套規范來處理SOAP消息。SOAP結點有責任遵守SOAP消息交換的規則以及提供通過依賴底層協議的SOAP綁定來訪問的服務。任何不符合SOAP約定的情況都將導致SOAP結點產生一個SOAP fault(SOAP錯誤)。
SOAP條目 (SOAP Block)
SOAP條目是一個句法上的結構,它用于包含一個邏輯上的單一元素,這一元素是需要被SOAP結點處理的。一個SOAP條目是由該條目最外層元素的完整修飾名(帶命名空間修飾)所標識的,這個完整修飾名是由一個局部名和一個命名空間URI組成的。封裝在SOAP Header中的SOAP條目稱為Header條目,而封裝在SOAP body中的SOAP條目為Body條目。
SOAP Header (SOAP頭)
能夠被SOAP消息傳輸路徑中任意的SOAP接受者結點處理的一組SOAP條目(0個或多個)。
SOAP Body (SOAP體)
能夠被SOAP消息路徑中的最終SOAP接受結點處理的一組SOAP條目(0個或多個)。
SOAP發送者
SOAP發送者是發出SOAP消息的SOAP結點。
SOAP接收者
SOAP接收者是接受SOAP消息的SOAP結點。
SOAP消息路徑
為傳送一個簡單的SOAP消息而要經過的一組SOAP發送者和SOAP接受者。其中包含了初始SOAP發送者、零個或多個SOAP中介結點以及最終的SOAP接受者。
初始SOAP發送者
SOAP消息的最初產生者,同時也是SOAP消息路徑的第一個結點。
SOAP中介結點
SOAP中介結點即是SOAP接收者也是SOAP發送者,是SOAP消息可到達的某一個應用程序。當SOAP消息沿著SOAP消息路徑傳輸時,SOAP中介結點將處理一組確定的SOAP條目,然后它將消息轉發給消息路徑的下一個SOAP結點,直至傳送到最終SOAP接收者。
最終SOAP接收者
由初始SOAP發送者指定的通過SOAP消息路徑傳送的SOAP消息的最終的接收者。如果在SOAP消息路徑中有SOAP結點產生了SOAP錯誤,那么SOAP消息將不會到達最終接收者。
同時SOAP/1.2使用了新的命名空間,命名空間前綴"env"和"enc"等關聯的SOAP/1.2命名空間分別位于:"http://www.w3.org/2001/06/soap-envelope"和"http://www.w3.org/2001/06/soap-encoding"。
SOAP角色與SOAP Header處理模式
當SOAP結點接受并處理一個SOAP消息的時候,該SOAP結點將被告知應當以一個或多個SOAP處理角色來處理,這些SOAP角色是由SOAP角色名來標識,SOAP角色名的具體表示是使用一個env:actor屬性來表示,其值是一個URI。
每個SOAP結點都必須以一個指定的角色來處理,也就是說任意一個SOAP結點都屬于這個角色,這個角色使用命名為"http://www.w3.org/2001/06/soap-envelope/actor/next"的SOAP角色來表示,同時可以按照需要應用零個或多個其他的SOAP額外角色,當然這些角色應當使用不同與前面介紹的這個SOAP角色名。
SOAP結點可以通過以匿名SOAP角色來實施處理以使得自己成為最終SOAP接收者。當SOAP結點在處理一個SOAP消息的時候,其表現出的SOAP角色在整個處理過程中不得更改。這是因為SOAP規范只涉及如何處理單個SOAP消息而無需考慮狀態(這也是SOAP設計目標之一的簡明性的體現),因此是否允許在處理單個SOAP消息的時候轉換角色是沒有意義的。
從本質上說,SOAP角色名是用來識別SOAP結點的,通常使用某種URI的形式,SOAP的角色名并沒有與路由或者消息交換的語義相聯系。舉例來說,一個SOAP角色可以被命名為一個用于在發送SOAP消息給適當SOAP結點中表示接收結點訪問入口的URI。相反,也有這樣一些SOAP角色的名字,這些名字或者直接和消息路由相聯系(例如,"http://example.org/banking/anyAccountMgr"),或者和路由沒有聯系(例如,當一個消息頭被用來攜帶這樣一種指示性的信息,該指示信息用于告知任何相關的SOAP消息的接受應用軟件,這個SOAP消息是長期不變的,因此是能夠被安全的緩存和重用的,在這種SOAP消息頭中,可以利用一個標識"所有緩存管理軟件"的URI來指明SOAP角色),通過名字使用這些SOAP角色也是合適的。
總而言之,SOAP角色的名并沒有預定義為一定要與某種語義相關聯,用戶可以使用某種語義關聯的URI來表示,也完全可以用類似UUID這樣的沒有語義的URI來表示,這完全要看具體的應用的需要。
SOAP Header條目包含可選的env:actor屬性,用來把他們定位到合適的SOAP結點。沒有該屬性的SOAP Header隱含地被定位到一個匿名的SOAP角色,這意味著他們將被最終SOAP接收者所處理。我們把SOAP actor屬性的值(隱含的或者直接指明的)作為相應SOAP條目(SOAP Header條目或者SOAP Body條目)的SOAP角色。
如果是:
- SOAP條目中SOAP actor屬性的值(如果出現的話)匹配了一個SOAP結點的角色;
- 或者是當SOAP條目沒有actor屬性(不僅對于SOAP Header條目有效,也同時包括SOAP Body條目,值得注意的是在SOAP/1.1中,actor屬性只能應用于SOAP Header條目),而該SOAP結點已經被假設為匿名SOAP角色。
這時我們就說SOAP條目被指向一個SOAP結點,同時將被該SOAP結點處理。
Figure 1. SOAP Header條目的標準化處理模式
我們認為隨著時間的過去,會有大量的SOAP Header函數規范出現,而且每個SOAP結點都可以包含一個或多個處理這些擴展所必須的軟件。如果SOAP結點的應用軟件是完全兼容而且實現了那些由條目中完整修飾的最外層元素名所傳遞的語義,我們說這個SOAP Header被一個SOAP結點理解。
在Figure 1中,以形象化的形式描述了這種將來可能的依據某種Header函數規范的標準化處理方式。其實質就是在SOAP的框架下,定義了一整套SOAP Header條目的語義集及其處理規范。例如,將來可能會出現一組專用于訪問控制的SOAP Header條目集。其中可能包含這樣兩種SOAP Header條目:(假定他們的命名空間為xmlns:auth="soap:header: authentication")
- 用戶認證:auth:get_authToken,在這個SOAP Header條目下,包含兩個子元素userID和password,用于完成用戶認證操作并獲取認證令牌;
- 訪問授權:auth:judge_accessList,在這個SOAP Header條目下,包含一系列的子元素accessResource,每個accessResource有兩個屬性authToken和resourceURI,分別用于表示提供的認證令牌和待訪問的資源URI,這個SOAP Header條目用于判定這些資源是否授權于給定的人證令牌以訪問權限,如果是,那么授予了什么樣的權限。
如果這樣一種SOAP Header條目的規范被投入實用后,任何SOAP結點只需要部署了兼容該規范的SOAP處理程序,就能夠處理這樣的SOAP Header條目。
對于SOAP結點而言,除env:actor屬性之外,尚有另一個重要的屬性:env:mustUnderstand。當定位到一個SOAP結點的SOAP Header條目的env:mustUnderstand屬性為"1",被指向的SOAP結點必須:
- 或者依照由條目中完整修飾的最外層元素名傳遞的語義來處理SOAP塊;
- 或者更本不處理SOAP消息而失敗。
也就是說,不可以在任何情況下忽略對這種SOAP Header條目的處理。
SOAP功能擴展: 權限認證
在以下的篇幅,將結合具體的應用實例來詳細地闡述SOAP Header條目的意義以及SOAP Header屬性的作用,同時期望大家能夠了解到從設計者的角度,是如何對SOAP進行體系架構的。
第一個例子是利用SOAP Header條目進行權限認證:
<env:Header xmlns:env="http://www.w3.org/2001/06/soap-envelope" >
<auth:authentication xmlns:auth="http://example.org/authentication "
env:actor="authentication:signin_service"
env:mustUnderstand="1">
<auth:userID>testuserid</auth:userID>
<auth:password>[encodedPassword]</auth:password>
<auth:redirection>http://example.com/service/</auth:redirection>
</auth:authentication>
</env:Header>
|
在這個例子中,SOAP Header條目authentication被交付給專門的權限認證Web服務進行用戶認證(該服務使用角色名"authentication:signin_service"來標識),該Web服務通過檢查authentication條目中包含的用戶名(userID)和密碼(password)來確認該用戶是否能通過認證檢查。如果無法通過認證檢查,將返回調用者一個SOAP錯誤,如果能夠通過認證檢查,則該認證Web服務在該Header條目中刪除userID和password,然后插入一個新的元素authInfo,這是一個認證令牌,可用于以后在需授權服務調用中使用。接著,該Web服務將這條消息傳遞給由redirection元素指定的地址的Web服務,這個Web服務可以通過校驗認證令牌以審核該次調用。
從認證Web服務發送到后續Web服務的SOAP消息中的Header片斷的可能內容可參見下面的代碼段:
<env:Header xmlns:env="http://www.w3.org/2001/06/soap-envelope" >
<auth:authentication xmlns:auth="http://example.org/authentication "
env:mustUnderstand="1" >
<auth:authInfo>[encodedAuthInfo]</auth:authInfo>
</auth:authentication>
</env:Header>
|
大家可以發現在這個后續的SOAP消息中,authentication條目中的redirection元素也已經被刪除了(也就是已經被使用了,作為新的SOAP結點的地址)。
SOAP功能擴展: 事務控制
第二個例子是利用SOAP Header條目進行事務控制。這個應用背景是這樣的,在一個商務事務處理應用環境中,由Web服務A發起事務,一個事務會包含多個操作,而這些操作可能要經過其他的一些Web服務進行計算后才能生成,而所有的操作將會被發往Web服務Z,由Web服務Z完成整個事務。整個事務的執行模式可參見下圖。
Figure 2. 事務控制模型
其中的消息序列將是這樣:
- Web服務A向Web服務Z發出事務啟動的總控消息;
- Web服務A向Web服務G、H、I發出操作生成請求消息;
- Web服務G、H、I分別向Web服務Z發出事務中的具體操作的描述消息,以最終完成整個事務。
也就是說Web服務A是事務的控制點,Web服務Z是事務的提交點,而Web服務G、H、I則分別是事務的產生點。
總控消息的Header片斷的內容為:
<env:Header xmlns:env="http://www.w3.org/2001/06/soap-envelope" >
<transaction:transaction
xmlns:transaction="http://example.org/transaction"
env:actor="transaction:submission_point">
env:mustUnderstand="1">
<transaction:transactionKey>8259bd00-2f9c-4493-a09f-414e3a4559a6
</transaction:transactionKey>
<transaction:operations>
<transaction:count>3</transaction:count>
</transaction:operations >
</transaction:Transaction>
</env:Header>
|
在這條消息中,有一個SOAP Header條目transaction,它的子元素transactionKey表示了啟動的事務的鍵值。而另一個子元素operations則包含了一個描述該事務包含的所有操作的數量的子元素count。當Web服務Z接受到這條消息后,將為該事務啟動一個消息池,該消息池的標識為transactionKey的值。
然后Web服務A向Web服務G、H、I發出事務啟動消息,通知這些服務指定事務可以開始提交操作了。
<env:Header xmlns:env="http://www.w3.org/2001/06/soap-envelope" >
<transaction:transaction
xmlns:transaction="http://example.org/transaction"
env:actor="transaction:operation_point" >
env:mustUnderstand="1">
<transaction:transactionKey>8259bd00-2f9c-4493-a09f-414e3a4559a6
</transaction:transactionKey>
<transaction:action>start</transaction:action>
</transaction:Transaction>
</env:Header>
|
當Web服務G、H、I分別向Web服務Z發出操作消息(參見圖 4 25)時,Web服務Z分別將這些收到的消息放入指定的消息池中,當消息池中的操作消息的數量達到count元素中指定的數量后,Web服務Z將關閉該消息池,按照次序,執行該事務,待執行完畢后,向Web服務A發送一個通知消息。
<env:Header xmlns:env="http://www.w3.org/2001/06/soap-envelope" >
<transaction:transaction
xmlns:transaction="http://example.org/transaction"
env:actor="transaction:submission_point" >
env:mustUnderstand="1">
<transaction:transactionKey>8259bd00-2f9c-4493-a09f-414e3a4559a6
</transaction:transactionKey>
<transaction:operations>
<transaction:serialNo>1</transaction:serialNo>
</transaction:operations >
</transaction:Transaction>
</env:Header>
|
小結
在本文中按照SOAP規范的約定,給出了兩個運用SOAP Header條目對SOAP的能力進行擴充的例子。我們認為,當具體的應用中運用了一些與應用本身關聯不是太大而更面向底層控制的服務的時候應當采用SOAP Header來傳輸這些控制信息,理由是這些服務往往是平臺的功能而非具體應用所要實現的功能。按照規范的約定,SOAP Body是專用于交換調用的具體信息,而控制信息的交互應當由SOAP Header來完成。
這樣,從體系架構的觀點來看,解析SOAP Header的就可以由平臺模塊來完成,通過插入不同的標準化的SOAP Header條目解析模塊來完成不同目的的控制功能。而相應的,解析SOAP Body是由應用模塊來完成。這樣在開發和部署上將會非常地清晰。
隨著SOAP Header擴展的普遍應用和標準的形成,將意味著SOAP技術的真正成熟。 |