在與許多客戶的接觸中,我發現有必要建立一套SOA的基本原則。下面的部分將介紹SOA中應有的基本原則。這些并非絕對真理,它們更像一個用于SOA相關討論的參考框架。你會發現:前四項衍生自Don Box提出的四項原則,盡管隨著時間的流逝,這四項原則的描述可能已經有了些變化。
相關廠商內容
1. 明確邊界:服務被調用時,與實現其功能相關的內容都應被傳遞過來。對服務的所有訪問都應該通過公共接口進行。調用服務時,非隱含的假設是必須的。“服務與消息緊密聯系,因為參數進出服務的唯一方式是通過消息進行的”。作為通用的模式,服務調用不應依賴于共享的上下文,而應被作為無狀態的模塊。契約描述了服務的功能性與非功能性的能力和特點,管理著服務提供的接口。服務調用是一個具有業務邏輯效果的行為,可能有大量的資源開銷,并且導致一系列不同于本地方法調用和遠程過程調用的錯誤。服務的調用絕非遠程過程調用。
服務的使用和提供應該盡可能地簡單,因此與服務間的交互沒必要被隱藏得太多。在SOA中,服務發送和接收的消息、服務契約以及服務本身都應當是最好的構件。這就意味著,例如,被用到的編程模型和工具至少應該提供一個API,這個API會幫助服務的編程人員了解上述概念。總的來說,一個明確的接口會封裝服務的內在實現,而服務通過該接口發布自己的功能;與服務交互是一個具體的行為,它依賴于服務使用者和提供者之間消息的傳遞。
2. 共享契約和架構,而不是類:基于一份服務描述(一份契約),服務使用者和服務提供者都可以獲得使用或提供服務的全部所需。根據松耦合原則,服務提供者不能依靠服務使用者來重用那些依賴于使用者環境的代碼。畢竟,服務使用者可能使用不同的開發環境和運行環境。這條原則給SOA體系中所能交換的數據加上了嚴格的限制。理想的情況是,數據以符合一種或多種模式的XML文檔形式被交換,因為這種方式可應用于任何你能想到的編程環境。因此,因為這條原則在基于DCOM和基于RMI的環境中是不可能被遵守的,所以這兩種環境基本上無法成為SOA的可用選項。
3. 策略驅動:為了與服務交互,必須滿足以下兩組不同的要求:
- 提供者提供的功能、語法和語義必須適應使用者的需求;
- 技術能力與需要必須匹配。
為了使盡可能多的形形色色的使用者能對服務進行訪問,一種策略機制已經被作為SOA工具集的一部分引入了。在服務接口對功能進行描述的同時,策略對不同的,非功能性的能力和需求進行了指定。(譯者注:策略指定的是服務之外的補充信息,是對服務使用者提出的特征要求)。
4. 自治:與明確邊界原則相關,服務自治意味著,接口成為服務與外界聯系的唯一方式,至少從SOA的角度來看是這樣的。需要注意的是,服務的運行環境一定是可變的。例如,在絲毫不影響使用者的情況下,就可以從輕量級的原型實現轉換到成熟的、基于應用服務器的協同組件集。服務能夠被彼此獨立的修改、部署、發布新版本和管理。服務提供者不能寄希望于服務使用者,期望它們依靠自己的能力迅速適應新版本的服務,有的使用者可能甚至沒這個能力或者根本不愿去適應新版本的服務接口(尤其是當這些服務接口超出了服務提供者控制范圍的時候)。
5. 采用可傳輸的協議格式,而非API:服務通常采用協議格式來發布,協議格式應該是明確的、可傳輸的并且被服務所支持的。這一點與前兩條原則非常相關,但卻帶來了新的見解:為保證一個服務最大程度的可訪問性(及長期的可用性),只要交互過程遵守為該服務定義的策略,那么由任何依照服務接口進行消息交換的平臺都可以訪問該服務。例如,通過以這一原則來測試主流的動態編程語言(如Perl、Python或Ruby),我們可以去考慮該語言能否使用或提供一個特定的服務。雖然,在現有的技術實現里,這條原則可能還沒有發揮作用,但這個思路可以作為下列準則的試金石:
- 使用開放的標準或者可閱讀的描述來描述所有消息格式。
- 不需要特定的資源就可以創造出符合這些合理的模式的消息。
- 成功通信所必需的附加信息,例如包含安全性或可靠性約束的頭信息,它們的語義和語法要遵循公開的規范和標準。
- 服務交互時所使用的傳輸(或傳遞)協議中至少有一個是標準的網絡協議,或它可以通過標準的網絡協議來訪問。
6. 面向文檔:服務交互時,數據是以文檔的形式來傳遞的。文檔是一個被明確模塊化的,有層次結構的數據容器。面向文檔的一個重要特征就是自描述。最理想的情況下,文檔是對現實世界中的文件(如訂單、發票或帳單)的建模。文檔應該被設計來確保它在問題域的上下文中發揮作用,這意味著它們可能應用于一個或更多的服務。
與現實世界的紙制文檔相似,和服務交換信息的文檔將包含冗余的信息。例如,文檔中可能同時包含了客戶ID和客戶地址信息(盡管客戶ID可能已經足夠了)。這種冗余是可以接受的,因為它將服務使用者和提供者雙方的服務接口和隱含數據模型隔離開來。應用面向文檔的模式的同時,服務調用成為有意義的業務邏輯消息的交換,而非上下文無關的RPC調用。雖然通常可以認為XML將被作為服務文檔的格式和語法,但它還沒有成為標準。
在一個SOA連接中,參與者之間的消息流轉于不同的系統,使得各個系統之間彼此獨立。松耦合原則要求參與者對共知的依賴越少越好。當消息在分布式對象或RPC基礎架構中發送時,客戶端和服務器端使用由同一個接口描述文檔生成的代理類(stub和skeleton)。如果不是這種情況的話,當契約不支持雙方的交互時,通訊就會停止。因為這個原因,RPC風格的基礎架構要求客戶端和服務器端程序代碼的同步運行。
7. 松耦合:多數SOA的倡導者都認為松耦合是一個很重要的概念。不幸的是,對于究竟哪些特征造成一個系統松耦合,有許多不同的看法。一個系統可以在多個維度表現為松耦合或緊耦合,它依賴于具體的要求和上下文,系統可能會在一些維度是松耦合的,在另一些維度是緊耦合的。這些維度包括:
- 時間:當參與者在時間上是松耦合時,它們不需要在同一時間啟動并進行通訊。這要求兩者之間采用某種緩沖或隊列機制,盡管這種機制與松耦合無關。當參與的一方向另一方發送消息時,交互的繼續不依賴于邏輯上或物理上能否立即返回應答消息。
- 位置:如果一方參與者查詢與之通信的另一方參與者的地址,另一方的地址可以透明地進行變更,不需要重新編程、重新配置或者甚至不需要通信伙伴的重新啟動。這意味著查找(lookup)過程采用某種目錄或地址來存儲服務終端的地址。(對應SOA提供的目錄服務)
- 類型:同靜態與動態,弱類型與強類型這些編程的概念類似,參與者既可以全部依賴也可以部分依賴文檔結構來實現它的功能。
- 版本:參與者可以依賴服務接口的特定版本,也可以兼容某個范圍內的版本。所需匹配的版本越確切,參與者在這個方面上的松耦合性就越差。一個好的原則是遵循Postel法則(譯者注:Postel’s Law——“Be liberal in what you accept, and conservative in what you send.”):服務提供者應盡可能兼容許多不同的版本,這將使它更加健壯(可能甚至需要容錯),服務使用者應盡可能遵循精確的語法和文檔類型。這將增加整個系統的穩定性和靈活性。
- 基數:服務消費者和提供者可能是1對1的關系,尤其是在請求或響應交互發生時,或隊列被明確使用的情況下。在別的情況下,服務使用者(在這種情況下,稱作“消息發送者”或“事件源”更為合理)可能既不知道也不關心有多少人接受了消息。
- 查找(Lookup):參與者打算調用服務時,既可以依賴服務提供者的物理名或邏輯名,也可以先通過一組功能描述來執行查找(lookup)操作。這意味著存在一個注冊表和(或)倉庫,對存儲其中的使用者需求和提供者能力進行直接或間接的匹配。
- 接口:參與者可能要綁定到一個特定的服務接口或是支持一個通用的接口。如果使用通用接口,所有該接口的使用者都能與所有該接口的提供者進行交互。盡管可能乍看起來這有些笨拙,但單一通用(統一)接口的原則就是WWW架構的核心。
8. 遵循標準:一個SOA應用中應遵循的一個關鍵原則是,信賴標準而非專有的API和格式。標準存在于技術方面,如數據格式、元數據、傳輸協議;也存在于業務層面,如文檔的類型。(例如,UBL中所提到的那些)(譯者注:UBL定義了業務文檔的通用XML庫,UBL的文檔類型包括訂單、發票等)
很顯然,一些人認為專有的解決方案,如一些EAI或消息服務提供商提供的方案,都遵循SOA原則。這個原則不遺余力地強調標準的重要性。當然,由于有太多可供選擇的標準,什么情況用何種標準成了頗具爭議的問題。標準的一個重要方面是它的可接受性(在Web服務的標準中,基本上可以認為“Microsoft肯定要插上一腳”)。
9. 獨立于軟件供應商:任何架構性的原則都不應依賴特定供應商的產品。將抽象的概念轉化為具體的,可運行的系統的過程中,不可避免的要決定使用何種具體的產品,包括商業的或者免費開源的軟件。這些決定都不應影響架構層。這就意味著要盡可能的依賴互操作性和可移植性的標準。因此,要應用支持適當標準的技術來構建服務提供者和使用者,不要受限于任何軟件供應商的技術路線。
10. 元數據驅動:SOA中所有的元數據對象都需要被按照一種方式儲存起來,這種方式將確保元數據對象能夠在設計和運行時被發現、檢索和解釋。元數據對象包括對服務接口、參與者、端點和綁定信息、組織單元和職責、文檔類型或模式、使用者或提供者關系等的描述。這些對象的用途應當是被代碼自動生成或者解釋,成為服務和參與者生命周期的一部分。
以上是我的原則列表。 即使你不完全同意——而坦率地講,我也不希望你完全同意, 至少不是全部都同意——我希望你能帶著它們來引發一些討論!