通過將這些原則應用到面向服務的體系結構設計,可以幫助通過IT靈活性實現業務靈活性遠景。
引言
面向服務的體系結構(Service-Oriented Architecture,SOA)提供了支持業務靈活性的IT靈活性遠景。在本文中,我們將重點討論IT靈活性的兩個特定方面:流程實現的分離和簡化。如何說明和實現各個服務對IT靈活性的這些方面有很大的影響,因此也對業務靈活性有很大的影響。我們此處的目標是提供支持SOA遠景的服務說明和實現指南。本文的論述結構如下:
·首先,我們將描述將在其中說明和實現服務和服務操作的上下文環境。我們將考慮SOA基礎結構的職責和服務的職責。
·接下來,我們將討論適用于整個服務(而不是各個操作)規范的設計原則。
·最后,我們將說明適用于各個服務操作的設計原則。
我們在文中所給出的設計原則旨在通過改善流程實現的分離和簡化來提高IT靈活性,因此,我們將通過對這些理念進行更為深入的分析來完成我們的介紹。
分離
SOA原則非常強調將服務使用者和服務提供者分離開來,關于此類分離實際的含義,有很多不正式但非常有用的約定。分離背后的一個基礎概念就是,對服務提供者的修改不應要求在服務使用者中進行相應的修改。例如,將當前在特定操作系統上運行的服務重新部署到另一個平臺的決定完全可能不要求對服務使用者進行更改。一個主要的SOA指導原則就是,要減少使用者和提供者之間的依賴關系。
分離應用于技術層面,強調Web服務和異步消息交付之類的技術,以允許使用者獨立于服務提供者選擇實現和可用性選項。我們還可以通過各種方式讓SOA基礎結構實現技術分離,如:
表1. 分離技術
服務應該設計為與要部署到其中的SOA基礎結構兼容,特別是,服務應確保避免不必要的耦合。舉個相反的例子,有狀態服務接口將傾向于通過將使用者與特定提供者實例關聯來增加使用者和提供者間的耦合。
分離的概念也同樣適用于非技術的業務層次。服務使用者應該盡可能與服務提供者實現的業務邏輯細節分離。為了實現此類分離,同樣也需要進行細心的設計。在下面的服務設計原則部分,我們將討論將服務接口表述為有意義的業務操作(而不是細粒度的原語方法)的好處。
流程實現
在SOA中,我們通過對各個服務進行編排(通過編程方式或使用基于業務流程執行語言——Business Process execution Language,BPEL——的工具)來實現業務流程。如果要實現SOA遠景,則必須簡化創建和修改流程的任務——即,服務編排任務。
業務流程編排的目標在于實際而有效地實現所需的業務邏輯。流程實現人員所面臨的問題包括:
·選擇恰當的服務操作
·確定使用正確參數調用服務的順序
·處理各種可能的響應,包括錯誤響應
應當清楚,服務設計的質量對編排簡化有很大的影響。有關服務、操作和參數的名稱和數量以及文檔質量和服務操作之間的相互依賴程度——所有設計問題——的決策都可能給編排帶來很大的影響。
SOA設計原則
這一部分是有關整個SOA系統的指南,代表了在建立系統時需要進行決策的各個方面。您將向設計人員和實現人員提供哪些規則和指導方針?您的SOA基礎結構將提供何種功能?我們將給出一系列建議設計原則,但每個都是設計過程中的一種折衷做法。您的企業可能有具體的要求,而需要選擇與我們提供的常規建議不同的選項。我們提出設計原則的目的在于標識需要進行決策的方面;而此類決策則是架構設計人員的責任。我們并不認為所提出的設計原則非常全面;在您的企業中實現SOA時,很有可能會采用其他原則,我們非常希望您能將這些設計原則反饋給我們。
SOA要求一致性
有很多可用于創建、發布、發現和調用服務的候選技術。SOA應提供一個參考體系結構,以指定服務提供者和使用者將使用的特定機制;我們應以在SAO所有參與者間實現一致性為目標。此類一致性可以減少開發、集成和維護工作。
如果需要使用參考體系結構之外的元素,我們推薦使用補充性方法。例如,假如我們為服務發布和發現選擇的機制是UDDI,但某個特定的開發團隊已在使用一個基于其他存儲庫技術的開發流程,此時該如何處理呢?我們將選擇投入精力將該團隊的服務同時發布到兩個存儲庫。這樣,現有的服務使用者就可以使用其熟悉(但可能并不標準)的存儲庫了。而運行于公共SOA基礎結構上的使用者則可以為所有服務使用標準存儲庫——例如UDDI。
SOA簡化開發
我們希望任何企業級的SOA基礎結構都具有可伸縮性和彈性;還應包含行業級的企業服務總線(EntERPrise Service Bus,ESB)和安全技術。或者,換種說法,以SOA為目標的服務和流程的開發人員可利用成熟的中間件,依賴SOA基礎結構提供問題的解決方案,如身份驗證、消息轉換和可靠消息交付。
這些中間件功能的提供應以一個重要的原則為基礎:服務和流程開發人員應遠離中間件實現的復雜細節。我們的理想目標是,在我們的SOA環境中工作的開發人員應只需要業務領域的相關知識和基本的編程技巧。
我們可以通過各種方式實現此目標,如下所述:
·聲明技術:J2EE編程模型就是使用聲明技術提供應用程序邏輯和中間件配置分離的一個例子。例如,應用程序組裝人員通過在部署描述符(而不是代碼)中添加相應條目來應用EJB方法角色的安全授權;然后部署人員會將這些角色映射到用戶和組。請注意,部署人員無需編寫任何授權代碼。
·抽象: 在某些情況下,SOA基礎結構中可以提供API,以用于特定的用途。例如,SOA基礎結構可以提供錯誤報告和審核機制。在設計此類API時應非常小心,要注意其易用性。我們應優先考慮聲明技術,而不是對這些機制進行編程配置。同樣,在標準API可用時(例如Java日志API),我們應通過這些標準API公開SOA基礎結構功能,而不是采用自己開發編寫的方式。
·代碼生成: 在無法避免代碼復雜性的地方,可以使用代碼生成技術。例如,Web服務描述語言(Web Services Definition Language,WSDL)就可以為開發人員隱藏SOAP、HTTP和JMS的復雜細節。這是通過組合用WSDL表示的可由計算機處理的接口定義和可從WSDL生成相關調用代碼的語言特定實現的工具來實現的。
·工具:在不可避免SOA基礎結構的細節進入開發人員代碼的情況下,我們可以通過使用合適的工具擴展開發環境來減少開發人員工作的復雜性。IBM Rational Software Development Platform產品所提供的基于Eclipse的環境可使用自定義插件、代碼片段和用戶指南輕松地進行擴展。
·模型驅動的開發:模型驅動的開發技術可以被視為前面兩種方法的特定復雜組合,同時利用了工具和代碼生成功能來簡化開發體驗。開發人員生成統一建模語言(Unified Modeling Language,UML)模型,此類模型可轉換為相應的代碼,其中包含利用SOA基礎結構所必需的代碼。
總之,在定義面向服務的體系結構及其基礎結構時,我們必須特別注意開發人員的需求。當為開發人員提供指南,以告知他們應如何開發或使用服務時,我們應該尋找可促進這些指導方針遵循的機制。一個總的原則是“只要可方便完成所需的工作,就說明方法是正確的。”換句話說,遵循相關指南應當為阻力最小的方法。SOA內的控制對其成功甚為關鍵。
從開發人員的角度而言,他們有責任了解SOA基礎結構和指南,并積極使用指南,而不要嘗試進行規避。
服務具有標準的、經過正式定義的可由計算機處理的接口
了解了工具和代碼生成在SOA實現中可扮演重要角色之后,我們現在要強調使用可由計算機處理的接口的重要性。當使用定義良好的可由計算機處理的語言描述了接口時,實際上就為各種工具支持功能提供了支持。我們希望改善分離狀況,因此我們強烈建議使用WSDL之類正式定義的開放標準語言,而不要使用專用格式。
可由計算機處理的方法的概念應該從服務接口描述(如WSDL)擴展到所有其他形式的聲明信息或元數據。只有同時強調聲明技術和可由計算機處理的元數據,才能將其相關的復雜性從業務應用程序開發人員轉移到基于標準的中間件中。新興的WS-Policy之類的技術在支持此方法方面充當著重要的角色。
服務應設計為可重用
服務設計人員應該記住,他們所開發的任何服務都可能成為可重用資產。設計人員不應只關注服務的最初使用者的需求,而應該進行更為廣泛的業務分析,以確定更全面的需求。我們建議,設計人員應考慮服務可能的發展方向:
·設計必須能適應不斷增加的吞吐量;如果服務在使用服務的數量增加的情況下仍可成功運行,那么使用率也會成級數遞增。
·如果使用服務的數量增加,則數據量和并發數據訪問模式可能會與最初投入使用時的情況大為不同。
·我們必須對服務請求的未來增長進行預計;新使用者可能需要其他的功能,或者需要對現有功能進行更改
文本其余部分所討論的很多設計原則都與確保服務的可伸縮性和可維護性密切相關。需要提醒一下:可能會由于考慮了潛在的重用而采用不恰當的設計方法對服務進行設計,從而導致實現“過當”。我們鼓勵將最初的重點放在服務接口設計上,以確保其支持可伸縮性;我們的設計原則可幫助做到這一點。然后生成一個該接口的戰術型實現,要求足以滿足目前已知的需求。假如該接口設計良好,應該可以在出現相關需求時替代伸縮性更好的實現。
服務設計原則
我們曾說過,服務是其接口采用某種一致認可的格式發布的服務操作的邏輯分組,那么我們接下來將討論適用于整個服務的設計原則。在下面的服務操作設計原則中,我們將討論各個操作的設計。
命名服務時應以最大化易用性為目標
我們在選擇服務、操作、數據類型和參數的名稱時有一個指導原則:希望最大化服務的易用性。我們希望幫助流程開發人員標識實現業務流程所需的服務和操作。因此,我們強烈建議使用服務使用者專業領域內有意義的名稱,優先選用業務概念而不是技術概念。
我們的建議就是:應使用名詞對服務進行命名;而應使用動詞對操作進行命名。
比較清單1和清單2中所示的兩個服務定義。我們使用簡化的偽代碼來減少編程語言“簇”。
清單1. 使用動詞短語和IT構造的服務定義
ManageCustomerData {
insertCustomerRecord()
updateCustomerRecord()
// etc ...
}
清單2. 使用名詞和動詞短語及業務概念的服務定義
CustomerService {
createNewCustomer()
ChangeCustomerAddress()
CorrectCustomerAddress()
EnableOverdraftFacilityForCustomer()
// etc ...
}
請注意清單1中的定義是如何使用IT概念進行表述并同時為服務和操作使用動詞短語的。在清單2中,服務表述為名詞,而操作則使用具有清楚的業務含義的動詞短語進行命名。我們認為第二個示例的易用性更好一些。此外,在第二個示例中,服務的業務用途非常清楚,而不單是僅僅指示其輸出。因此,我們不使用“update customer record”(可以為出于任何原因進行的任何更新),而使用“enable overdraft facility”。與此類似,在客戶搬遷時,我們使用“change customer address”方法更改客戶地址;而在希望更正無效數據時使用“correct customer address”更正客戶地址,因為這樣很容易看出這兩個操作采用了不同的服務邏輯。
如果采用業務概念表述服務和操作名稱,則必須密切注意如何確定這些名稱。這就非常需要有一個正式的術語詞匯表,可以通過業務分析活動得到這個詞匯表。詞匯表應該有一個正式的所有者。
服務應具有精心選擇的粒度
粒度 一詞在SOA相關討論中有多種不同的用法。在本文的服務設計討論中,我們考慮的是服務本身的粒度,即服務應該包含的操作數量。
沒有可用于確定服務粒度的簡單啟發式方法。我們將提供兩個在設計服務時應該考慮的因素的示例加以說明:
·服務將通常作為測試和發布的單位。如果粒度過粗,而將大量操作分組到單個服務中,則可能將增加服務的使用者。因此,如果我們對服務的某些方面進行更改(可能僅為了其中一些使用者的利益),則必須重新發布整個服務,從而可能影響所有使用者。
·服務使用者所面臨的一個挑戰就是找到正確的操作。通常,使用者需要瀏覽服務列表,然后在標識了合適的服務后瀏覽服務操作列表。我們認為,服務粒度的兩個極端——提供僅有幾個方法的很多服務,或數十或數百個操作均集中在幾個服務中——都將對易用性造成影響。
這表明,在選擇服務粒度時,我們可能需要在多個因素間進行折衷,如可維護性、可操作性和易用性。任何給定的SOA都應向服務設計人員提供指南,以便確定此類折衷方案。
服務應是內聚而完整的
既然認識到了在確定服務粒度時需要考慮周全,那么在確定哪些操作應組成服務時有什么注意事項呢?我們認為有兩個對象設計概念很有用:內聚性和完整性。我們可將這些概念應用于服務接口。
我們希望創建功能內聚的接口,一組操作由于其功能相關而聚合到一起。我們發現,當評估內聚程度時,從服務使用者角度看待服務很有用。通過使用者的視角,我們會將重點放在服務的功能上。將此方法與使用以下內聚標準進行對比:
·我們可以考慮基于功能實現的內聚性進行決策。是否應由于操作使用相同的算法分組到一起,或者由于均是使用相同主機上的CICS事務實現的而將其分組到一起?這些是實現細節,不應影響接口設計。
·可以使用時間內聚性原則,即,將在短時間內一起使用的操作分組到一起,例如,RetrieveCustomerDetails、CheckCreditRating、createLoanFacility和TransferFunds操作都可能在金融業務流程中依次出現。不過,時間內聚性并不意味著這些操作應該由同一個服務提供,CheckCreditRating和TransferFunds就缺乏功能內聚性。
使用名詞-動詞對服務和操作進行命名的規則可以幫助我們將重點放在服務接口的功能內聚性上。我們可以問這樣一個問題“這個動詞是否是該名詞所進行的操作?”
我們的第二個對象設計概念是完整性概念。在為已知使用者創建服務時,完整性的問題尤為值得注意。在這種情況下,我們通常會將重點放在滿足所知的使用者需求上。請務必記住,服務應該為可重用的,因此需要考慮將來的使用者的可能需求。舉個簡單的例子,假如有個名為CellPhone的服務提供create、update、Query、delete和Deactivate等操作。我們完全可以想象會需要對棄用的手機進行重新激活,因此應決定是否也應提供對稱的Activate方法。
通過判斷,我們應該應用完整性規則。如果不知道使用者需求,則可能很難提供正確的功能,因此就有可能存在將開發和測試工作浪費在提供將不會使用的操作上的風險。
服務應對實現細節進行封裝
另一個對象設計原則(封裝)也適用于設計服務接口。我們封裝服務實現的細節——所用的算法和資源——的動機在于增加服務使用者和提供者之間的分離,從而為將來擴展提供靈活性。
服務適應多種調用模式
WebSphere等提供的Web服務技術允許進行更高層次的封裝。服務使用者通過使用各種調用模式,可以使用完全相同的代碼技術來調用Web服務,如以下這些模式:
·使用SOAP over HTTP的傳統同步調用
·使用SOAP over JMS的基于消息的異步調用
·使用Java過程調用的本地調用
不過,雖然Web服務基礎結構可以封裝調用的細節,從而簡化代碼,但服務設計也應對調用方式加以考慮。對比一下本地調用和遠程調用。與清單3所示內容類似的服務設計可以提供有價值的業務功能,但卻不適合在很多SOA環境中部署。
清單3. 繁忙型服務接口
LibraryCatalogService {
// search operations elided
String getBookTitle(String isbn)
String getBookAuthor(String isbn)
Date getBookPublicationDate(String isbn)
// further operations elided
}
轉載請注明出處:拓步ERP資訊網http://www.guhuozai8.cn/
本文標題:實現SOA服務設計原則是什么?(上)