精彩的人生

          好好工作,好好生活

          BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
            147 Posts :: 0 Stories :: 250 Comments :: 0 Trackbacks
          發(fā)布日期: 12/15/2005 | 更新日期: 12/15/2005

          John Evdemon

          Microsoft Corporation, Architecture Strategy 團(tuán)隊(duì)

          適用于:

          ?

          企業(yè)體系結(jié)構(gòu)

          ?

          面向服務(wù)的體系結(jié)構(gòu)

          ?

          Web 服務(wù)

          摘要:“服務(wù)設(shè)計(jì)的原則”系列文章旨在彼此交流這方面的最佳實(shí)踐經(jīng)驗(yàn)和示例代碼。本文是系列文章中的第一篇,主要提供基本的 Web 服務(wù)設(shè)計(jì)和實(shí)現(xiàn)原則,簡(jiǎn)要介紹了“面向服務(wù)的體系結(jié)構(gòu)”(SOA) 的概念,詳細(xì)討論了開發(fā)人員在構(gòu)建 Web 服務(wù)時(shí)可以利用的幾種模式和反模式。這些原則適用于任何可以開發(fā)和部署 Web 服務(wù)的編程語(yǔ)言或平臺(tái)。

          Microsoft Patterns & Practices 團(tuán)隊(duì) Ron Jacobs 一篇網(wǎng)絡(luò)廣播的啟發(fā)

          本文中的許多觀點(diǎn)和概念源自 Patterns and Practices 團(tuán)隊(duì)的 Ron Jacobs,特此感謝。2004 年底,Ron 和我基于這些內(nèi)容撰寫了一篇網(wǎng)絡(luò)廣播。如果沒(méi)有 Ron 的幫助,本文是無(wú)法完成的。

          要了解關(guān)于 Ron 在 Patterns and Practices 團(tuán)隊(duì)所做工作的更多信息,請(qǐng)參閱 http://www.microsoft.com/resources/practices/default.mspxhttp://www.gotdotnet.com/team/rojacobs/

          下載本文相關(guān)資料:

          服務(wù)設(shè)計(jì)的原則:以文檔為中心的模式(英文)。

          服務(wù)設(shè)計(jì)的原則:冪等模式(英文)。

          服務(wù)設(shè)計(jì)的原則:預(yù)訂模式(英文)。

          *
          本頁(yè)內(nèi)容
          關(guān)于 SOA 設(shè)計(jì)原則系列文章 關(guān)于 SOA 設(shè)計(jì)原則系列文章
          簡(jiǎn)介面向服務(wù)的體系結(jié)構(gòu) (SOA) 簡(jiǎn)介面向服務(wù)的體系結(jié)構(gòu) (SOA)
          SOA 模式與反模式 SOA 模式與反模式
          結(jié)論 結(jié)論

          關(guān)于 SOA 設(shè)計(jì)原則系列文章

          本文是系列文章中的第一篇,集中討論如何設(shè)計(jì)更有效的 Web 服務(wù)。此開篇文章是與 Microsoft 的 patterns & practices 團(tuán)隊(duì)合作完成的,今后我們還會(huì)與 Microsoft 內(nèi)部和外部的其他團(tuán)隊(duì)和個(gè)人合作。

          讀者應(yīng)慎用“SOA 設(shè)計(jì)原則系列”開發(fā)的示例代碼。示例代碼僅用于演示目的,鼓勵(lì)讀者研究、編譯和學(xué)習(xí)這些代碼。讀者應(yīng)避免在生產(chǎn)環(huán)境中嘗試使用任何示例代碼。如果讀者決定在生產(chǎn)環(huán)境中使用任何示例代碼,MICROSOFT 對(duì)其造成的損害不承擔(dān)任何責(zé)任。

          示例代碼的系統(tǒng)要求:

          ?

          Microsoft Windows XP(示例未在其他平臺(tái)上測(cè)試)

          ?

          Microsoft .NET Framework 1.1

          ?

          Microsoft Internet Information Server 6.0

          ?

          Microsoft SQL Server 或 Microsoft Access

          ?

          Microsoft Visual Studio 2003 不是必需的,但如果使用會(huì)使總體效果更佳

          雖然 Microsoft 對(duì)于示例代碼不提供支持,但本文的作者仍歡迎您給予反饋。

          注意 由于 SOA 正在快速發(fā)展,隨著它的不斷成熟,本系列中的文章和示例代碼可能會(huì)有修訂。

          返回頁(yè)首 返回頁(yè)首

          簡(jiǎn)介面向服務(wù)的體系結(jié)構(gòu) (SOA)

          目前,SOA 已成為廣為人知而且存在些分歧的縮寫詞。如果要兩個(gè)人給 SOA 下個(gè)定義,可能會(huì)有兩個(gè)差別懸殊、甚至可能是截然對(duì)立的答案。有人將 SOA 描述為啟動(dòng)業(yè)務(wù)的 IT 基礎(chǔ)結(jié)構(gòu),而其他人則認(rèn)為 SOA 可以提高 IT 的效率。在許多方面,SOA 有點(diǎn)像 John Godfrey Saxe 的那首盲人與象的詩(shī):每個(gè)人對(duì)那頭象都有不同的描述,因?yàn)樗麄兌际艿搅烁髯越?jīng)驗(yàn)的影響(例如,摸到象鼻子的人認(rèn)為它是條蛇,而摸到象牙的人則認(rèn)為它是矛)。相對(duì)而言,Saxe 先生的象還是很容易描述的,因?yàn)樗吘故钦鎸?shí)存在的實(shí)體:而 SOA 更加難以描述,因?yàn)樵O(shè)計(jì)思想是無(wú)法以物理形式表現(xiàn)的。

          SOA 是用于從自治服務(wù)構(gòu)建系統(tǒng)的體系結(jié)構(gòu)方法。有了 SOA,集成更具前瞻性,而不是事后反思:最終的解決方案可能由以不同編程語(yǔ)言開發(fā)的服務(wù)組成,由具有各種安全模型和業(yè)務(wù)流程的不同平臺(tái)托管。盡管這一概念聽起來(lái)驚人的復(fù)雜,它卻并不是新生事物:有人認(rèn)為,SOA 是從基于先前可用技術(shù)設(shè)計(jì)和開發(fā)分布式系統(tǒng)的經(jīng)驗(yàn)演化而來(lái)的。與 SOA 相關(guān)的許多概念,如服務(wù)、發(fā)現(xiàn)和后期綁定,都與 CORBA 和 DCOM 有關(guān)。同樣,許多服務(wù)設(shè)計(jì)原則與早期基于封裝、抽象和定義明確的接口的 OOA/OOD 技術(shù)有著許多共同之處。

          縮寫詞 SOA 提出了一個(gè)很明顯的問(wèn)題:到底什么是服務(wù)?簡(jiǎn)而言之,服務(wù)即可以通過(guò)定義明確的消息交換進(jìn)行交互的程序。服務(wù)的設(shè)計(jì)必須考慮可用性和穩(wěn)定性。服務(wù)的構(gòu)建要考量持久性,而服務(wù)配置和聚合的構(gòu)建則要考量變化性。靈活性經(jīng)常上升為 SOA 的一個(gè)最大優(yōu)勢(shì):與受底層單一性應(yīng)用程序的約束、最小的變動(dòng)也要幾個(gè)星期才能實(shí)現(xiàn)的組織相比,在松散耦合的基礎(chǔ)結(jié)構(gòu)上實(shí)現(xiàn)業(yè)務(wù)流程的組織對(duì)于變動(dòng)要開放得多。松散耦合的系統(tǒng)會(huì)帶來(lái)松散耦合的業(yè)務(wù)流程,因?yàn)闃I(yè)務(wù)流程不再受底層基礎(chǔ)結(jié)構(gòu)局限性的約束。服務(wù)及其關(guān)聯(lián)接口必須保持穩(wěn)定,以便能夠重新配置或重新聚合來(lái)滿足日新月異的業(yè)務(wù)需求。服務(wù)的穩(wěn)定性依賴于基于標(biāo)準(zhǔn)的接口和定義明確的消息:即,用于消息定義的 SOAP 和 XML 架構(gòu)。如果服務(wù)用于執(zhí)行簡(jiǎn)單而精確的功能、幾乎不知道消息是如何傳遞過(guò)來(lái)的或是如何檢索出來(lái)的,那么它在更大的 SOA 基礎(chǔ)結(jié)構(gòu)中被重用的可能性更大。如前所述,在我們?cè)O(shè)計(jì)和構(gòu)建可重復(fù)使用的 Web 服務(wù)時(shí),應(yīng)當(dāng)回顧有關(guān)封裝和接口設(shè)計(jì)的 OO 設(shè)計(jì)原則。通過(guò)進(jìn)一步理解常說(shuō)的面向服務(wù)的“四條原則”,我們可以將這些 OO 原則擴(kuò)展到 Web 服務(wù)領(lǐng)域。

          原則 1:邊界是顯式的

          通過(guò)跨越定義明確的邊界進(jìn)行顯式消息傳遞,服務(wù)得以彼此交互。有時(shí)候,跨越服務(wù)邊界可能要耗費(fèi)很大的成本,這要視地理、信任或執(zhí)行因素而定。邊界是指服務(wù)的公共接口與其內(nèi)部專用實(shí)現(xiàn)之間的界線。服務(wù)的邊界通過(guò) WSDL 發(fā)布,可能包括說(shuō)明特定服務(wù)之期望的聲明。跨越邊界之所以被認(rèn)為是代價(jià)高昂的任務(wù),是有多種原因的,下面列出其中幾個(gè):

          ?

          目標(biāo)服務(wù)的物理位置可能是未知的因素。

          ?

          安全和信任模型可能會(huì)在每次跨越邊界時(shí)發(fā)生改變。

          ?

          在服務(wù)的公共表示和專用表示之間封送和轉(zhuǎn)換數(shù)據(jù)可能需要依賴額外的資源:其中一些資源可能在服務(wù)之外。

          ?

          服務(wù)的構(gòu)建要考量持久性,而服務(wù)配置的構(gòu)建則要考量變化性。這一事實(shí)暗示著:由于網(wǎng)絡(luò)重新配置或者遷移到另一個(gè)物理位置,可靠的服務(wù)的性能可能會(huì)突然降低。

          ?

          服務(wù)的使用者通常不知道專用的內(nèi)部過(guò)程是如何實(shí)現(xiàn)的。特定服務(wù)的使用者對(duì)正使用的服務(wù)的性能只能進(jìn)行有限的控制。

          面向服務(wù)的集成(英文)模式告訴我們“服務(wù)調(diào)用可能會(huì)受到網(wǎng)絡(luò)滯后、網(wǎng)絡(luò)故障和分布式系統(tǒng)故障的影響,而本地實(shí)現(xiàn)則不會(huì)。要預(yù)先考慮使用遠(yuǎn)程對(duì)象接口的影響,就必須編寫大量的錯(cuò)誤檢測(cè)和更正邏輯。”盡管我們認(rèn)為跨越邊界是代價(jià)高昂的過(guò)程,但在部署用于將此類邊界跨越減至最少的本地方法時(shí),我們還是要格外謹(jǐn)慎。實(shí)現(xiàn)單一性本地方法和對(duì)象的系統(tǒng)可能會(huì)獲得性能的改善,但功能性卻與先前定義的服務(wù)完全一樣(此項(xiàng)技術(shù)在 OOP 中稱為“剪切與粘貼”,同樣存在服務(wù)版本更新的風(fēng)險(xiǎn))。

          關(guān)于第一條 SO 原則,有幾點(diǎn)原則需要銘記在心:

          ?

          弄清邊界。服務(wù)提供一個(gè)合約來(lái)定義其提供的公共接口。與服務(wù)的所有交互都通過(guò)公共接口進(jìn)行。接口由公共進(jìn)程和公共數(shù)據(jù)表示組成。公共進(jìn)程是通向服務(wù)內(nèi)部的入口點(diǎn),而公共數(shù)據(jù)表示則是指該進(jìn)程使用的消息。如果我們使用 WSDL 代表一個(gè)簡(jiǎn)單的合約,則 <message> 代表公共數(shù)據(jù),而 <portType> 代表公共進(jìn)程。文章“外部數(shù)據(jù)與內(nèi)部數(shù)據(jù)”(英文)更詳細(xì)地研究了這些問(wèn)題。

          ?

          服務(wù)應(yīng)易于使用。設(shè)計(jì)服務(wù)時(shí),開發(fā)人員應(yīng)使其易于其他開發(fā)人員使用。設(shè)計(jì)的服務(wù)接口(合約)也應(yīng)允許服務(wù)在不中斷與現(xiàn)有使用者之間的合約的情況下進(jìn)一步發(fā)展。(這一主題將在本系列的后續(xù)文章中更詳細(xì)地討論。)

          ?

          避免使用 RPC 接口。應(yīng)采用顯式消息傳遞,而避免使用 RPC 之類的模型。這種方法將使用者與服務(wù)實(shí)現(xiàn)的內(nèi)部隔離開來(lái),使開發(fā)人員可以集中精力改進(jìn)他們的服務(wù),同時(shí)將對(duì)服務(wù)使用者的影響降至最低(使用公共消息而不是公用的方法進(jìn)行封裝)。

          ?

          盡量減小服務(wù)的表面積。服務(wù)的公共接口越多,就越難以使用和維護(hù)。應(yīng)當(dāng)少提供服務(wù)的定義明確的公共接口。這些接口應(yīng)該相對(duì)簡(jiǎn)單,主要用于接受定義明確的輸入消息并以同樣定義明確的輸出消息進(jìn)行響應(yīng)。這些接口一旦定義,即應(yīng)保持不變。這些接口提供服務(wù)必須支持的“恒定不變”的設(shè)計(jì)要求,為服務(wù)專用的內(nèi)部實(shí)現(xiàn)充當(dāng)門面。

          ?

          內(nèi)部(專用)實(shí)現(xiàn)的細(xì)節(jié)不應(yīng)泄露到服務(wù)邊界之外。如果將實(shí)現(xiàn)細(xì)節(jié)泄露到服務(wù)邊界,很可能會(huì)使服務(wù)與服務(wù)使用者之間的耦合更加緊密。服務(wù)使用者不應(yīng)當(dāng)獲知服務(wù)實(shí)現(xiàn)的內(nèi)部情況,因?yàn)檫@樣會(huì)使服務(wù)的版本更新或升級(jí)受到限制。本文的“反模式”部分就此問(wèn)題提供了一個(gè)詳細(xì)的示例。

          原則 2:服務(wù)具有自治性

          服務(wù)是獨(dú)立進(jìn)行部署、版本控制和管理的實(shí)體。開發(fā)人員應(yīng)避免對(duì)服務(wù)邊界之間的空間進(jìn)行假設(shè),因?yàn)榇丝臻g比邊界本身更容易改變。例如,服務(wù)邊界應(yīng)當(dāng)是不變的,只有這樣才能將版本更新對(duì)使用者的影響降至最低。雖然服務(wù)邊界是相當(dāng)穩(wěn)定的,但策略、物理位置或網(wǎng)絡(luò)拓?fù)涞确?wù)部署選項(xiàng)卻很可能發(fā)生改變。

          服務(wù)可以通過(guò) URI 動(dòng)態(tài)尋址,使其底層位置和部署拓?fù)淇梢栽趲缀醪挥绊懛?wù)本身的情況下改變或演化(服務(wù)的通信通道也是如此)。盡管這些更改對(duì)服務(wù)沒(méi)什么影響,但它們對(duì)使用服務(wù)的應(yīng)用程序卻有著破壞性的影響。如果您今天使用的服務(wù)明天被移動(dòng)到新西蘭,將會(huì)怎樣呢?響應(yīng)時(shí)間的改變可能會(huì)對(duì)服務(wù)的使用者造成計(jì)劃之外或意料之外的影響。服務(wù)設(shè)計(jì)者對(duì)于服務(wù)的使用方式應(yīng)當(dāng)采取謹(jǐn)慎的態(tài)度:服務(wù)將失敗,其相關(guān)的行為(服務(wù)級(jí)別)可能會(huì)被更改。適當(dāng)級(jí)別的例外處理和補(bǔ)償邏輯必須與任何服務(wù)調(diào)用相關(guān)聯(lián)。此外,服務(wù)使用者可能需要修改其策略,以聲明要使用的最短服務(wù)響應(yīng)時(shí)間。例如,服務(wù)使用者可以對(duì)安全、性能、事務(wù)及許多其他因素請(qǐng)求不同的服務(wù)級(jí)別。可配置的策略允許單個(gè)服務(wù)支持多個(gè)有關(guān)服務(wù)調(diào)用的 SLA(而其他策略可能主要關(guān)注版本更新、本地化及其他問(wèn)題)。服務(wù)級(jí)的通信性能期望始終是自治,因?yàn)榉?wù)彼此之間不需要熟悉對(duì)方的內(nèi)部實(shí)現(xiàn)。

          不止是服務(wù)使用者應(yīng)該對(duì)性能采取謹(jǐn)慎的態(tài)度:服務(wù)提供者在預(yù)測(cè)其服務(wù)的使用方式時(shí)也應(yīng)同樣謹(jǐn)慎。應(yīng)該預(yù)料到服務(wù)使用者有時(shí)候會(huì)失敗,卻又不通知服務(wù)本身。服務(wù)提供者也不能信任使用者總是“為所應(yīng)為”。例如,使用者可能會(huì)嘗試使用不正常的/惡意的消息進(jìn)行通信,或者嘗試違反成功實(shí)現(xiàn)服務(wù)交互所必需的其他策略。無(wú)論用戶意圖如何,服務(wù)內(nèi)部都必須嘗試對(duì)此類不恰當(dāng)?shù)氖褂眠M(jìn)行補(bǔ)償。

          雖然服務(wù)是自治的,但任何服務(wù)都不是孤島。基于 SOA 的解決方案是不規(guī)則的,由許多為特定解決方案配置的服務(wù)組成。從自治的角度思考,您很快就會(huì)發(fā)現(xiàn)面向服務(wù)的環(huán)境中并沒(méi)有主領(lǐng)機(jī)構(gòu):編排服務(wù)中的“指揮器”概念是錯(cuò)誤的(進(jìn)一步意味著,跨服務(wù)的“回滾”概念也是錯(cuò)誤的:但這最好留待在另一篇文章中討論)。實(shí)現(xiàn)自治服務(wù)的關(guān)鍵是隔離和去耦合。服務(wù)都彼此獨(dú)立地設(shè)計(jì)和部署,并且只能使用合約驅(qū)動(dòng)的消息和策略進(jìn)行通信。

          至于其他服務(wù)設(shè)計(jì)原則,我們可以學(xué)習(xí)過(guò)去 OO 設(shè)計(jì)的經(jīng)驗(yàn)。Peter Herzum 及 Oliver Sims 就 Business Component Factories 的著作提供了對(duì)自治組件特性的一些有趣見解。雖然他們大部分的工作最適于大粒度、基于組件的解決方案,但其基本設(shè)計(jì)原則仍然適用于服務(wù)設(shè)計(jì)。

          鑒于這些考量,在此提供一些有助于確保符合第二條 SO 原則的簡(jiǎn)單設(shè)計(jì)原則:

          ?

          服務(wù)的部署和版本控制應(yīng)獨(dú)立于部署和使用它們的系統(tǒng)。

          ?

          合約的設(shè)計(jì)應(yīng)符合以下假設(shè),即一旦公布即不可修改。這種方法迫使開發(fā)人員在其架構(gòu)設(shè)計(jì)中構(gòu)建靈活性。

          ?

          采取謹(jǐn)慎的態(tài)度,使服務(wù)免于故障。從使用者的角度,規(guī)劃服務(wù)可用性和性能的不可靠級(jí)別。從提供者的角度,預(yù)計(jì)服務(wù)會(huì)被誤用(故意或其他方式),預(yù)計(jì)服務(wù)使用者會(huì)出現(xiàn)故障:而服務(wù)可能得不到通知。

          原則 3:服務(wù)共享架構(gòu)和合約,但不共享類

          如上所述,服務(wù)交互應(yīng)當(dāng)只以服務(wù)的策略、架構(gòu)和基于合約的行為為基礎(chǔ)。服務(wù)的合約通常使用 WSDL 定義,而服務(wù)聚合的合約則可以使用 BPEL 定義(進(jìn)而,對(duì)聚合的每個(gè)服務(wù)使用 WSDL)。

          大多數(shù)開發(fā)人員定義類來(lái)代表特定問(wèn)題空間中的各種實(shí)體(例如,“客戶”、“訂單”和“產(chǎn)品”)。類將行為與數(shù)據(jù)(消息)組合到一個(gè)特定于編程語(yǔ)言或平臺(tái)的構(gòu)造函數(shù)。服務(wù)打破了這種模式,最大程度提高了靈活性和互操作性。使用基于 XML 架構(gòu)的消息進(jìn)行通信的服務(wù)獨(dú)立于編程語(yǔ)言與平臺(tái),從而拓寬了互操作性的級(jí)別。架構(gòu)用于定義消息的結(jié)構(gòu)和內(nèi)容,而服務(wù)合約則用于定義服務(wù)本身的行為。

          總起來(lái)說(shuō),服務(wù)的合約由以下元素組成:

          ?

          使用“XML 架構(gòu)”定義的消息交換格式。

          ?

          使用 WSDL 定義的“消息交換模式”(MEP)。

          ?

          使用 WS-Policy 定義的功能和要求。

          ?

          BPEL 可以用作業(yè)務(wù)流程級(jí)合約,用以聚合多個(gè)服務(wù)。

          服務(wù)使用者將依靠服務(wù)的合約來(lái)調(diào)用服務(wù)及與服務(wù)交互。鑒于這種依賴性,服務(wù)合約必須長(zhǎng)期保持穩(wěn)定。在利用 XML 架構(gòu) (xsd:any) 和 SOAP 處理模型(可選標(biāo)頭)的可擴(kuò)展性的同時(shí),合約的設(shè)計(jì)應(yīng)盡可能明確。

          “第三條原則”的最大挑戰(zhàn)是其持久性。服務(wù)合約一旦公布,要想修改它而又盡可能減小對(duì)現(xiàn)有服務(wù)使用者的影響,是極其困難的。內(nèi)部數(shù)據(jù)表示與外部數(shù)據(jù)表示之間的界線對(duì)于特定服務(wù)的成功部署和重用至關(guān)重要。公共數(shù)據(jù)(在服務(wù)之間傳遞的數(shù)據(jù))應(yīng)基于組織或縱向標(biāo)準(zhǔn),確保能夠跨不同服務(wù)被廣泛接受。私有數(shù)據(jù)(服務(wù)內(nèi)部的數(shù)據(jù))封裝在服務(wù)之內(nèi)。在某種程度上,服務(wù)就像是實(shí)施電子商務(wù)交易的組織的縮微代表。如同組織必須將外來(lái)采購(gòu)訂單映射為其內(nèi)部 PO 格式一樣,服務(wù)也必須將通過(guò)合約達(dá)成一致的數(shù)據(jù)表示映射為其內(nèi)部格式。與前面一樣,我們可以再次使用 OO 數(shù)據(jù)封裝經(jīng)驗(yàn)來(lái)闡明類似的概念:服務(wù)的內(nèi)部數(shù)據(jù)表示只能通過(guò)服務(wù)合約處理。Pat Helland 在“外部數(shù)據(jù)與內(nèi)部數(shù)據(jù)”(英文)中探討了幾個(gè)關(guān)于公共數(shù)據(jù)表示與私有數(shù)據(jù)表示的問(wèn)題。

          鑒于這些考量,在此提供一些有助于確保符合第三條 SO 原則的簡(jiǎn)單設(shè)計(jì)原則:

          ?

          確保服務(wù)合約保持穩(wěn)定,以將對(duì)服務(wù)使用者的影響降至最低。這里的合約指公共數(shù)據(jù)表示(數(shù)據(jù))、消息交換模式 (WSDL) 和可配置的功能和服務(wù)級(jí)別(策略)。

          ?

          合約的設(shè)計(jì)應(yīng)盡可能明確,以將誤解減至最少。此外,應(yīng)通過(guò) XML 語(yǔ)法和 SOAP 處理模型的可擴(kuò)展性使合約能夠適應(yīng)未來(lái)服務(wù)的版本更新。

          ?

          避免使公共數(shù)據(jù)表示與私有數(shù)據(jù)表示之間的界線混淆不清。使用者不應(yīng)看到服務(wù)的內(nèi)部數(shù)據(jù)格式,而其公共數(shù)據(jù)架構(gòu)應(yīng)不可改變(最好基于組織標(biāo)準(zhǔn)、事實(shí)標(biāo)準(zhǔn)或行業(yè)標(biāo)準(zhǔn))。

          ?

          當(dāng)不可避免要更改服務(wù)合約時(shí),要對(duì)服務(wù)進(jìn)行版本控制。這種方法對(duì)現(xiàn)有使用者實(shí)現(xiàn)的破壞程度最小。

          原則 4:服務(wù)兼容性基于策略

          盡管它往往被認(rèn)為是最不為人所了解的原則,但對(duì)于實(shí)現(xiàn)靈活的 Web 服務(wù),它或許是最有力的。單純依靠 WSDL 無(wú)法交流某些業(yè)務(wù)交互要求。可以使用策略表達(dá)式將結(jié)構(gòu)兼容性(交流的內(nèi)容)與語(yǔ)義兼容性(如何交流消息或者將消息交流給誰(shuí))分隔開來(lái)。

          服務(wù)提供者的操作要求可以通過(guò)計(jì)算機(jī)能識(shí)別的策略表達(dá)式來(lái)表現(xiàn)。策略表達(dá)式提供一組可以配置的可互操作語(yǔ)義,用以控制特定服務(wù)的行為和期望。WS-Policy 規(guī)范定義了一個(gè)計(jì)算機(jī)能識(shí)別的策略框架,它可以表達(dá)服務(wù)級(jí)策略,使它們得以在運(yùn)行時(shí)被發(fā)現(xiàn)或?qū)嵤@纾踩?wù)可能需要一個(gè)實(shí)施特定服務(wù)級(jí)別的策略(例如,必須對(duì)照恐怖分子識(shí)別系統(tǒng)對(duì)符合指定條件的護(hù)照像片進(jìn)行交叉檢查)。與此項(xiàng)服務(wù)關(guān)聯(lián)的策略信息可以用于許多與實(shí)施背景檢查有關(guān)的其他情形或服務(wù)。WS-Policy 無(wú)需任何額外代碼即可用于實(shí)現(xiàn)這些要求。本例闡明策略框架如何在提供業(yè)務(wù)定義和執(zhí)行的聲明編程模型的同時(shí),提供有關(guān)服務(wù)要求的附加信息。

          策略聲明可以確定哪些行為是策略主體的要求(或功能)。(在上面的例子中,聲明是指對(duì)照恐怖分子識(shí)別系統(tǒng)進(jìn)行背景檢查。)聲明提供特定于域的語(yǔ)義,并最終在各縱向行業(yè)的單獨(dú)、特定于域的規(guī)范之內(nèi)定義(建立 WS-Policy “框架”概念)。

          盡管策略驅(qū)動(dòng)的服務(wù)仍然在不斷發(fā)展,但開發(fā)人員仍應(yīng)確保其策略聲明在服務(wù)期望和服務(wù)語(yǔ)義兼容性方面盡可能明確。

          返回頁(yè)首 返回頁(yè)首

          SOA 模式與反模式

          既然您已經(jīng)對(duì) SOA 概念(包括 SO 設(shè)計(jì)原則)有所了解,就讓我們開始將學(xué)習(xí)到的知識(shí)付諸實(shí)踐吧。本文余下篇幅將介紹兩個(gè)“反模式”和三個(gè)“模式”。這些“反模式”和“模式”都建立在前述概念的基礎(chǔ)之上。

          為什么使用模式和反模式?

          人們的思考和交流往往遵循一些模式。幾部關(guān)于模式語(yǔ)言的書籍的作者 Christopher Alexander 將模式定義為“由在特定的非任意上下文中不斷出現(xiàn)的具體形式概括出來(lái)的抽象概念”。可通過(guò)模式和模式語(yǔ)言描述最佳實(shí)踐方法、已被認(rèn)可的設(shè)計(jì)并記錄過(guò)去經(jīng)驗(yàn),在某種程度上供他人從中學(xué)習(xí)。模式是快速理解設(shè)計(jì)原則和它們所應(yīng)用的各種環(huán)境的有效方法。而如您所料,反模式與模式相對(duì)。模式提供實(shí)踐證明的指導(dǎo)原則和最佳經(jīng)驗(yàn),而反模式則闡明常見的設(shè)計(jì)缺陷,用于吸取他人的教訓(xùn)。本文余下的篇幅簡(jiǎn)略介紹兩個(gè)反模式和三個(gè)模式,它們都可以幫助開發(fā)更有效的 Web 服務(wù)。

          本文中的反模式和模式遵循下列格式:

          ?

          上下文:模式或反模式的簡(jiǎn)要背景。提供上下文是為了幫助讀者在徹底實(shí)例化之前發(fā)現(xiàn)可能應(yīng)用模式或識(shí)別出反模式特征的機(jī)會(huì)。

          ?

          問(wèn)題:簡(jiǎn)單的描述,旨在制定與模式或反模式相關(guān)的目標(biāo)。

          ?

          影響因素:應(yīng)用特定模式或識(shí)別反模式時(shí)必須考慮的其他事項(xiàng)。

          ?

          解決方案:對(duì)特定反模式的解決方案或應(yīng)用相關(guān)模式的必要步驟的描述。

          ?

          故障現(xiàn)象與后果:對(duì)于反模式,是指導(dǎo)致反模式存在的因素。對(duì)于模式,故障現(xiàn)象與后果可以描述在應(yīng)用相關(guān)模式之前要考慮的其他因素和事項(xiàng)。

          反模式中還包括關(guān)于如何改進(jìn)相關(guān)設(shè)計(jì)缺陷的其他建議。

          關(guān)于代碼示例的說(shuō)明

          ?

          每個(gè)模式的代碼示例都可以下載。

          ?

          每個(gè)示例均已包裝為安裝文件 (MSI),并且提供說(shuō)明示例的安裝和配置方法的 README 文件。

          ?

          如上所述,讀者應(yīng)慎用示例代碼。示例代碼僅用于演示目的,盡管我們鼓勵(lì)讀者研究、編譯和學(xué)習(xí)這些代碼,但讀者應(yīng)避免在生產(chǎn)環(huán)境中嘗試使用任何示例代碼。如果讀者決定在生產(chǎn)環(huán)境中使用任何示例代碼,MICROSOFT 對(duì)其造成的損害不承擔(dān)任何責(zé)任。

          反模式 1:CRUDy 接口

          ?

          上下文:

          ?

          您需要為新公司 SOA 項(xiàng)目設(shè)計(jì) Web 服務(wù)。

          ?

          問(wèn)題:

          ?

          如何使用 .NET 設(shè)計(jì) SOA 服務(wù)?

          ?

          影響因素:

          ?

          自 Visual Basic 5 后,您一直是 Visual Basic 開發(fā)人員,“知道”如何創(chuàng)建組件。

          ?

          這是您的第一個(gè) SOA 項(xiàng)目。

          ?

          您所在的組織希望其他平臺(tái)應(yīng)用程序使用您的服務(wù)。

          ?

          解決方案:

          ?

          就像過(guò)去設(shè)計(jì)組件接口那樣設(shè)計(jì)服務(wù)接口。

          ?

          創(chuàng)建實(shí)現(xiàn) CRUD(創(chuàng)建、讀取、更新、刪除)操作的服務(wù)。

          ?

          示例代碼段如代碼清單 1 所示。

          代碼清單 1. Visual Basic .NET CRUD 服務(wù)示例

          <WebMethod()> _
          Public Sub Create( ByVal CompanyName As String, ByVal 
          ContactName As String, ByVal ContactTitle As String, 
          ByVal Address As String, ByVal City As String, ByVal 
          State As String, ByVal Zip As String, ByVal Country As 
          String, ByVal Telephone As String, ByVal Fax As String) 
          
          <WebMethod()> _
          Public Function MoveNext() As Boolean
          End Function
          
          <WebMethod()> _
          Public Function Current() As Object
          End Function
          
          <WebMethod()> _
          Public Sub UpdateContactName( ByVal NewName as String)
          End Sub
          
          <WebMethod()> _
          Public Function CommitChanges()
          End Function
          

          故障現(xiàn)象與后果:

          ?

          此接口設(shè)計(jì)鼓勵(lì) RPC 形式的行為,即調(diào)用 Create、MoveNext 等等,而不是發(fā)送用于指示要采取哪些操作的定義明確的消息。這違反了第一條(定義明確的邊界)和第三條(只共享架構(gòu))原則。

          ?

          接口的通信很可能過(guò)度頻繁而瑣碎,因?yàn)槭褂谜呖赡苄枰{(diào)用兩三個(gè)方法才能完成其工作。

          ?

          對(duì) Create 方法使用 Sub 意味著使用者無(wú)從知道操作是成功還是失敗。設(shè)計(jì)服務(wù)時(shí),始終要牢記使用者的期望:使用者需要知道什么?

          ?

          CRUD 操作對(duì)于 Web 服務(wù)是錯(cuò)誤的分解級(jí)別。CRUD 操作可以在服務(wù)內(nèi)部或不同服務(wù)之間實(shí)現(xiàn),但是不應(yīng)以這種方式提供給使用者。有些服務(wù)允許內(nèi)部(私有)功能提供給服務(wù)公共接口,這就是一例。

          ?

          此接口意味著將發(fā)生有狀態(tài)的交互,如枚舉(參見 MoveNextCurrent 函數(shù))。

          ?

          抽象類型(如 Current 函數(shù)返回的 Object)將導(dǎo)致弱合約。這是違反第三條原則(只共享架構(gòu))的又一例。

          ?

          這是一個(gè)非常危險(xiǎn)的服務(wù),因?yàn)樗赡軙?huì)使底層數(shù)據(jù)處于不一致的狀態(tài)。如果使用者添加新的“聯(lián)系人”(或者更新現(xiàn)有“聯(lián)系人”),而從不調(diào)用 CommitChanges 函數(shù),那樣會(huì)發(fā)生什么情況呢?如前所述,服務(wù)提供者不能信任使用者總是“為所應(yīng)為”。

          按以下列方式更改服務(wù)后,可以避免上列風(fēng)險(xiǎn)和問(wèn)題:

          ?

          將服務(wù)接口改為使用 XML 架構(gòu)進(jìn)行通信。架構(gòu)還可以包括目標(biāo)服務(wù)操作(例如,“新建聯(lián)系人架構(gòu)”或“更改聯(lián)系人架構(gòu)”)。開發(fā)自己的架構(gòu)之前,開發(fā)人員應(yīng)參考現(xiàn)有行業(yè)標(biāo)準(zhǔn)。滿足您需要的架構(gòu)可能已經(jīng)存在。

          ?

          將數(shù)據(jù)處理封裝在私有方法之內(nèi),只能使用傳遞給公共接口的架構(gòu)訪問(wèn)。

          ?

          確保服務(wù)使用者收到包含請(qǐng)求狀態(tài)的確認(rèn)。

          反模式 2:Loosey Goosey

          ?

          上下文:

          ?

          要構(gòu)建一個(gè)基于服務(wù)的解決方案。

          ?

          您的組織對(duì)服務(wù)的重用很重視。

          ?

          問(wèn)題:

          ?

          如何使服務(wù)接口有最大的靈活性和可擴(kuò)展性?

          ?

          影響因素:

          ?

          您計(jì)劃在解決方案的所有級(jí)別提供集成點(diǎn)。

          ?

          其他組需要訪問(wèn)您的數(shù)據(jù)庫(kù)。

          ?

          解決方案:

          ?

          將您的服務(wù)接口設(shè)計(jì)為“數(shù)據(jù)級(jí)”(參見“代碼清單 2”)。

          ?

          重視后期綁定來(lái)設(shè)計(jì)高擴(kuò)展性的接口。

          代碼清單 2. Visual Basic .NET 數(shù)據(jù)級(jí)服務(wù)示例

          <WebMethod()> _
          Public Function QueryDatabase( ByVal Database as String, 
          SQLQuery as string) As DataSet
          
          <WebMethod()> _
          Public Function Execute( ByVal Command as Integer, 
          Arguments as string) As Boolean
          

          故障現(xiàn)象與后果:

          ?

          實(shí)際上沒(méi)有合約存在。服務(wù)使用者不知道如何使用服務(wù)(例如,什么是有效的“Command”參數(shù)和編碼期望等等)。

          ?

          接口接受消息時(shí)太過(guò)自由。合約既不清晰,又存在嚴(yán)重的安全風(fēng)險(xiǎn),容易受到 SQL 插入代碼攻擊。

          ?

          合約沒(méi)有提供足夠的信息讓使用者知道如何使用服務(wù)。如果使用者必須讀取服務(wù)簽名之外的一些信息才能了解如何使用服務(wù),那么應(yīng)檢查服務(wù)的分解。

          ?

          使用者需要在使用 Web 服務(wù)之前熟悉數(shù)據(jù)庫(kù)和表格結(jié)構(gòu)。這將導(dǎo)致服務(wù)提供者和使用者之間發(fā)生緊耦合。

          ?

          由于依賴后期綁定和在同一服務(wù)內(nèi)邊界之間的編碼/解碼,服務(wù)的運(yùn)行性能大大降低。

          按以下列方式更改服務(wù)后,可以避免上列風(fēng)險(xiǎn)和問(wèn)題:

          ?

          將服務(wù)合約改為使用定義明確的 XML 架構(gòu)進(jìn)行通信。架構(gòu)不應(yīng)提供有關(guān)底層數(shù)據(jù)倉(cāng)庫(kù)的任何信息。架構(gòu)的語(yǔ)義應(yīng)該為服務(wù)使用者提供上下文,使它們能夠了解服務(wù)的目的。(這一方法還可以提高服務(wù)的性能。)

          ?

          數(shù)據(jù)庫(kù)交互應(yīng)封裝在私有方法之內(nèi),使使用者與數(shù)據(jù)庫(kù)及其關(guān)聯(lián)表格的詳細(xì)信息隔離。

          ?

          確保服務(wù)使用者收到包含請(qǐng)求狀態(tài)的確認(rèn)。

          模式 1:文檔處理器

          此模式的示例代碼可以下載。

          ?

          上下文:

          ?

          要構(gòu)建一個(gè)基于服務(wù)的解決方案。

          ?

          應(yīng)符合 SO 設(shè)計(jì)原則。

          ?

          問(wèn)題:

          ?

          如何創(chuàng)建簡(jiǎn)單易用、定義明確而又符合 SO 設(shè)計(jì)原則的合約?

          ?

          影響因素:

          ?

          服務(wù)的合約應(yīng)鼓勵(lì)以文檔為中心的設(shè)計(jì)思路。

          ?

          合約應(yīng)清晰地定義服務(wù)語(yǔ)義(避免 Loosey Goosey 反模式)。

          ?

          合約應(yīng)將實(shí)現(xiàn)封裝在服務(wù)之內(nèi)或之后來(lái)促進(jìn)松散耦合(避免“CRUDy 接口”反模式)。服務(wù)合約是不得泄露有關(guān)內(nèi)部實(shí)現(xiàn)的詳細(xì)信息的邊界(回憶第一條設(shè)計(jì)原則)。

          ?

          服務(wù)必須符合 WS-I Basic Profile(英文),以允許支持 Web 服務(wù)的任何平臺(tái)或編程語(yǔ)言使用。

          ?

          服務(wù)應(yīng)作為一個(gè)完整的工作單元來(lái)表示業(yè)務(wù)流程(避免類似“CRUDy 接口”反模式中的有狀態(tài)假設(shè))。如前所述,服務(wù)提供者不能信任服務(wù)使用者總是“為所應(yīng)為”。服務(wù)不應(yīng)依靠調(diào)用另一服務(wù)的用戶在發(fā)生異常時(shí)“回滾”或“修復(fù)”狀況。

          ?

          解決方案:

          ?

          定義或重用 XML 架構(gòu)以表示服務(wù)的請(qǐng)求和響應(yīng)消息。確保與服務(wù)之間的所有公共交互都使用這些架構(gòu)。(有關(guān)示例代碼段,請(qǐng)參閱“代碼清單 3”。)

          ?

          直接從架構(gòu)生成對(duì)象,以加速開發(fā)。有時(shí)候,這稱為“合約至上”方法。利用“合約至上”的方法,應(yīng)在開發(fā)實(shí)際服務(wù)之前定義服務(wù)合約。然后可以使用服務(wù)合約生成服務(wù)代碼。“合約至上”對(duì)于減少互操作性阻礙是有效的方法,因?yàn)樗⒃跀?shù)十年經(jīng)驗(yàn)的基礎(chǔ)之上(CORBA、COM 和 DCE 都使用接口語(yǔ)言)。Web 服務(wù)有時(shí)采取“合約末位”方法,因?yàn)楹?jiǎn)單的解決方案通常使用 SOAP 而不是 WSDL。無(wú)論如何,許多開發(fā)環(huán)境提供對(duì)“合約至上”的簡(jiǎn)單支持,而 WSCF(英文)和 XSD Object Code Generator(XSD 對(duì)象代碼生成器)(英文)之類的工具可用于幫助進(jìn)一步自動(dòng)化此過(guò)程。

          ?

          如前所述,服務(wù)提供者不能期望使用者以特定方式調(diào)用或使用其服務(wù)。這意味著對(duì)給定事務(wù)使用補(bǔ)償過(guò)程是可行的,但是服務(wù)提供者不應(yīng)依靠服務(wù)使用者觸發(fā)補(bǔ)償。預(yù)訂模式(見下)為事務(wù)提供最自治的保護(hù),消除了對(duì)服務(wù)使用者的依賴。

          代碼清單 3. C# 文檔處理器服務(wù)示例

          [WebMethod()]
          
          public FindCustomerByCountryResponse FindCustomersByCountry(
          FindCustomerByCountry request) 
          {
             ...
          }
          

          故障現(xiàn)象與后果:

          使用此簡(jiǎn)單模式定義的服務(wù)將符合 SO 設(shè)計(jì)原則:

          ?

          以文檔為中心的 Web 服務(wù)更容易映射到業(yè)務(wù)流程,因?yàn)槭褂谜咄鶎I(yè)務(wù)流程看成發(fā)送和接收文檔(注意,文檔可能代表業(yè)務(wù)事件,而不是實(shí)際的業(yè)務(wù)文檔)。

          ?

          服務(wù)邊界相當(dāng)于在公共數(shù)據(jù)表示與私有數(shù)據(jù)表示之間進(jìn)行轉(zhuǎn)換時(shí)的清晰界線。

          ?

          服務(wù)的實(shí)現(xiàn)細(xì)節(jié)被封裝起來(lái),不讓使用者知悉。

          ?

          采取“合約至上”方法有助于確保服務(wù)的高度可互操作性。

          ?

          以文檔為中心的服務(wù)易于改進(jìn),因?yàn)樗薪换ザ纪ㄟ^(guò)消息發(fā)生,而不是通過(guò)硬編碼的 RPC 方法。

          對(duì)于此方法,有一些小問(wèn)題應(yīng)該注意:

          ?

          對(duì)于從內(nèi)部表示到外部表示的數(shù)據(jù)傳輸,性能可能會(huì)成為一個(gè)問(wèn)題。

          ?

          服務(wù)使用者必須將其數(shù)據(jù)表示映射到服務(wù)使用的架構(gòu)。某些使用者可能會(huì)發(fā)現(xiàn)映射到服務(wù)架構(gòu)是一個(gè)得不償失的過(guò)程。

          模式 2:冪等消息

          此模式的示例代碼可以下載。

          ?

          上下文:

          ?

          應(yīng)符合 SO 設(shè)計(jì)原則。

          ?

          要構(gòu)建一個(gè)基于服務(wù)的事務(wù)性解決方案。

          ?

          如果要多次傳送同一條消息,必須能夠補(bǔ)償服務(wù)(例如,消息應(yīng)當(dāng)是冪等的)。

          ?

          問(wèn)題:

          ?

          如何能夠確保消息是冪等的?

          ?

          影響因素:

          ?

          除了定義服務(wù)的合約,不能期望從使用者獲得更多信息。

          ?

          要實(shí)現(xiàn)需要頻繁、可靠更新的事務(wù)性數(shù)據(jù)庫(kù)系統(tǒng)。

          ?

          可靠的消息傳遞平臺(tái)可能并不能完全解決問(wèn)題,因?yàn)槭褂谜呖赡苋詴?huì)發(fā)送同一請(qǐng)求的多個(gè)副本。

          ?

          解決方案:

          ?

          服務(wù)合約(架構(gòu))應(yīng)要求使用者的消息帶有“工作單元”標(biāo)識(shí)符(此后稱為 UOW ID)。參見“圖 1”示例。

          ?

          合約不能要求隨著時(shí)間的變化 UOW ID 始終唯一。

          ?

          無(wú)論具有同一 UOW ID 值的消息數(shù)量有多少,UOW ID 始終代表僅執(zhí)行一次的工作單元。

          ?

          服務(wù)將使用 UOW ID 確定工作單元在啟動(dòng)之前是否已經(jīng)執(zhí)行過(guò)。處理與已經(jīng)完成的工作關(guān)聯(lián)的 UOW ID 時(shí),有三個(gè)可能的選項(xiàng):

          ?

          返回響應(yīng)的緩存副本。

          ?

          重新處理消息,就好像從未收到第一個(gè)請(qǐng)求一樣。

          ?

          引發(fā)異常,返回錯(cuò)誤消息。

          a

          1. 冪等消息模式

          ?

          故障現(xiàn)象與后果:

          冪等消息傳送是一個(gè)棘手的問(wèn)題。處理重復(fù) UOW ID 有三個(gè)選項(xiàng),對(duì)其中的每個(gè)選項(xiàng)都有若干要考慮的地方:

          1.

          返回緩存的響應(yīng):此選項(xiàng)要求服務(wù)將可能的響應(yīng)緩存維護(hù)一段給定時(shí)間。超時(shí)值/緩存刷新的確定應(yīng)該由關(guān)聯(lián)業(yè)務(wù)流程執(zhí)行。其他還必須考慮的問(wèn)題:

          ?

          如果當(dāng)前值與緩存值不同怎么辦?

          ?

          如果響應(yīng)錯(cuò)誤怎么辦?

          ?

          如果使用者重復(fù)使用無(wú)關(guān)工作單元的 UOW ID 怎么辦?

          2.

          再次處理消息:雖然這對(duì)簡(jiǎn)單的讀操作可能無(wú)害,但對(duì)寫操作(例如,發(fā)票付款)則可能有害。如果在第一次收到 UOW ID 時(shí)對(duì)它的處理導(dǎo)致錯(cuò)誤將會(huì)怎么樣??再次處理似乎將導(dǎo)致同樣的錯(cuò)誤(這種情況有時(shí)稱為“有毒消息循環(huán)”)。

          3.

          引發(fā)異常:這種情況下,服務(wù)使用者可能未收到服務(wù)的原始響應(yīng),而只是再次重新發(fā)送同一 UOW ID(可能因?yàn)轭A(yù)期響應(yīng)超時(shí))。如果最后一個(gè)發(fā)送的消息丟失,使用者將如何接收您的響應(yīng)?

          UOW ID 應(yīng)該是請(qǐng)求架構(gòu)的組成部分,將重復(fù)請(qǐng)求綁定到相關(guān)業(yè)務(wù)流程中。UOW ID 也可能是作為自定義 SOAP 標(biāo)頭添加的,從而使重復(fù)處理成為總體消息處理基礎(chǔ)結(jié)構(gòu)的組成部分。使用者的 URI 也應(yīng)包括在內(nèi),以幫助檢測(cè)重入。可以自動(dòng)維護(hù)修改的審核追蹤,使修改請(qǐng)求跟蹤能夠返回給定的 UOW ID。最后,與緩存“刷新”關(guān)聯(lián)的問(wèn)題可以通過(guò)反映收到請(qǐng)求時(shí)的響應(yīng)來(lái)解決。緩存管理是超出本文范圍的又一個(gè)難題。(建議有興趣詳細(xì)了解緩存問(wèn)題的讀者查看 MSDN 文章并發(fā)處理:設(shè)計(jì)服務(wù)與其代理之間的交互(英文)。

          由于服務(wù)不再相信使用者能“為所應(yīng)為”,故支持冪等消息傳送提高了服務(wù)自治性(第一條設(shè)計(jì)原則)。對(duì)于此方法,有一些小問(wèn)題應(yīng)該注意:

          ?

          使用此模式的服務(wù)將有可能使用大容量持久存儲(chǔ),以滿足響應(yīng)的緩存需求。

          ?

          由于管理緩存,可能會(huì)對(duì)服務(wù)性能造成嚴(yán)重影響。

          模式 3:預(yù)訂

          此模式的示例代碼可以下載。

          ?

          上下文:

          ?

          應(yīng)符合 SO 設(shè)計(jì)原則。

          ?

          您有一個(gè)打算通過(guò) Web 服務(wù)呈現(xiàn)給使用者的復(fù)雜的業(yè)務(wù)流程。該業(yè)務(wù)流程運(yùn)行時(shí)間長(zhǎng),一個(gè)事務(wù)就要持續(xù)幾個(gè)小時(shí)。

          ?

          問(wèn)題:

          ?

          如何在長(zhǎng)時(shí)間運(yùn)行的流程中保持?jǐn)?shù)據(jù)一致性?

          ?

          影響因素:

          ?

          無(wú)法共享分布式事務(wù)。

          ?

          上述業(yè)務(wù)流程需要若干消息才能完成。

          ?

          消息交換所需時(shí)間從幾秒鐘到幾個(gè)小時(shí)不等。

          ?

          解決方案:

          ?

          消息引起試探性操作:這些試探性操作為原子事務(wù),使數(shù)據(jù)庫(kù)保持一致狀態(tài)。

          ?

          可能的結(jié)果有三種,它們與這些試探性操作中的每個(gè)操作都相關(guān):

          ?

          試探性操作(通過(guò)完成消息交換)被確認(rèn)。

          ?

          試探性操作被取消,或者是因?yàn)楫a(chǎn)生了故障(隱式),或者是被一個(gè)參與者取消(顯式)。

          ?

          試探性操作(消息交換)未在期望的服務(wù)級(jí)別內(nèi)完成(超時(shí))。

          ?

          要跟蹤每個(gè)試探性操作的狀態(tài),必須定義一個(gè)對(duì)話框。如果為每個(gè)對(duì)話框指定一個(gè)唯一標(biāo)識(shí)符(“預(yù)訂 ID”)和過(guò)期時(shí)間戳,可使服務(wù)“記住”每個(gè)對(duì)話框停止的位置。圖 2 顯示此模式的說(shuō)明。

          ?

          如果服務(wù)使用者試圖確認(rèn)先前注冊(cè)的預(yù)訂,則該使用者必須提供有效的“預(yù)訂 ID”。缺少“預(yù)訂 ID”或者“預(yù)訂 ID”無(wú)效的確認(rèn)請(qǐng)求將被服務(wù)拒絕。

          ?

          過(guò)期時(shí)間戳使服務(wù)可以在超過(guò)給定時(shí)間段之后,使未確認(rèn)的預(yù)訂“過(guò)期”。

          a

          2. 預(yù)訂模式

          ?

          故障現(xiàn)象與后果:

          ?

          指定唯一的“預(yù)訂 ID”和過(guò)期時(shí)間戳可確保數(shù)據(jù)一致性問(wèn)題由服務(wù)及其關(guān)聯(lián)業(yè)務(wù)規(guī)則處理。如前所述,服務(wù)不能信任使用者“為所應(yīng)為”。

          ?

          “預(yù)訂 ID”用于跟蹤給定對(duì)話框的狀態(tài)。

          ?

          過(guò)期時(shí)間戳用于以可預(yù)測(cè)方式處理超時(shí)或者丟失的消息。

          “預(yù)訂 ID”和過(guò)期時(shí)間戳應(yīng)該是“確認(rèn)請(qǐng)求”架構(gòu)的一部分,將預(yù)訂處理綁定到實(shí)際業(yè)務(wù)過(guò)程中。服務(wù)為每個(gè)預(yù)訂請(qǐng)求生成“預(yù)訂 ID”和過(guò)期時(shí)間戳,使服務(wù)能夠定期檢查未確認(rèn)的預(yù)訂并使其“過(guò)期”。此模式可以與“冪等消息”模式組合,進(jìn)而將服務(wù)與重復(fù)的預(yù)訂請(qǐng)求隔離。

          對(duì)于此方法,有一些小問(wèn)題應(yīng)該注意:

          ?

          處理預(yù)訂請(qǐng)求的業(yè)務(wù)規(guī)則必須定義清晰。將如何處理“預(yù)訂超量”?

          ?

          我們有點(diǎn)被原子兩段提交模型擾亂了,常常試圖將其應(yīng)用于不很適合的場(chǎng)合(例如,運(yùn)行時(shí)間長(zhǎng)的過(guò)程)。運(yùn)行時(shí)間長(zhǎng)的過(guò)程必須保持組成它們的原子過(guò)程的一致性。運(yùn)行時(shí)間長(zhǎng)的過(guò)程中的工作隔離不是件簡(jiǎn)單的事情,像“預(yù)訂”這樣的模式是解決此問(wèn)題的簡(jiǎn)單嘗試。

          返回頁(yè)首 返回頁(yè)首

          結(jié)論

          四條“面向服務(wù)”原則提供了一組分立的基本原則,可用于指導(dǎo)服務(wù)開發(fā)工作。本文提供了幾個(gè)模式和反模式,旨在說(shuō)明這些原則如何影響服務(wù)設(shè)計(jì)。我們還提供了一些其他準(zhǔn)則,用于幫助確保您將來(lái)的服務(wù)設(shè)計(jì)和開發(fā)工作獲得成功:

          ?

          分解服務(wù)時(shí),根據(jù)現(xiàn)有文檔和已知業(yè)務(wù)事件為業(yè)務(wù)過(guò)程建模。

          ?

          雖然服務(wù)接口靈活很重要,但要避免太過(guò)靈活,以防底層服務(wù)合約變得不清晰。

          ?

          不要期望服務(wù)使用者“為所應(yīng)為”。如果服務(wù)要求使用者以預(yù)先定義好的方式執(zhí)行一系列步驟,請(qǐng)借助于模式(例如,預(yù)訂)幫助強(qiáng)制執(zhí)行這些步驟。

          ?

          永遠(yuǎn)不要使服務(wù)或其關(guān)聯(lián)資源處于不一致的狀態(tài)。

          還有許多其他設(shè)計(jì)問(wèn)題與 Web 服務(wù)關(guān)聯(lián)。本系列的后續(xù)文章將討論諸如版本控制、服務(wù)分解和策略驅(qū)動(dòng)的服務(wù)配置等問(wèn)題。

          轉(zhuǎn)到原英文頁(yè)面


          原文地址:http://www.microsoft.com/china/msdn/library/architecture/architecture/architecturetopic/SOADesign.mspx?mfr=true

          posted on 2006-09-27 11:04 hopeshared 閱讀(811) 評(píng)論(0)  編輯  收藏 所屬分類: Web Service
          主站蜘蛛池模板: 绵阳市| 太康县| 静海县| 浮山县| 南丹县| 泰来县| 饶河县| 巩义市| 建宁县| 磴口县| 呈贡县| 虹口区| 曲沃县| 会泽县| 绥滨县| 屯昌县| 宁津县| 吴堡县| 泉州市| 贵定县| 迁安市| 公主岭市| 英吉沙县| 阳曲县| 汶上县| 泌阳县| 永川市| 宜良县| 雷波县| 商洛市| 德昌县| 台东市| 冀州市| 徐水县| 九龙城区| 昭苏县| 祥云县| 贵州省| 长春市| 乳源| 邓州市|