SOA服務設計與實現的幾個語言無關的原則速記


一、SOA定義

SOA即面向服務架構(Service-Oriented Architecture)。在SOA中,一切皆服務。一個服務是通過消息交換來調用的程序,一個信息系統是共同完成一個特定任務的一組服務,SOA可以概述為一種由一組自治服務創建信息系統的方法。當然具體定義SOA真不好說,反正不能簡單理解為我們常用的開發技術如web服務、.net remoting或者wcf。

SOA設計四項基本原則:

1. 邊界必須明確

2. 服務必須自治

3. 服務分享 Schema 和 Contract, 而不是 Class

4. 由 Policy 決定服務間的兼容性

 

二、面向對象和面向服務

1、面向對象(OO)
a、應用於同一平台和運行環境

b、共享類型而不是Schema

c、采用便宜, 透明通信

d、對象的標識與生命周期由系統維護

e、客戶機和服務器的同步的部署

f、容易概念化,因而提供一個自然的模型

g、一般不需要狀態管理

h、應用於一個可預測的序列、期限和結果

i、目標是遠程透明地使用方法和類型

 

2、面向服務(SO)
a、應用於異構平台和運行環境

b、共享Schema而不是類型

c、采用高成本, 明確通信

d、服務是自治的: 安全和失效是隔離

e、允許的連續, 分離部署客戶機和服務器

f、基於軟件組件和分布的對象,依賴服務的協議

g、擁有並維護狀態

h、基於消息, 異步的, 以及長通信

i、目標是提供服務隔離和調用的標准

 

三、SOA反模式

1、CRUD型接口

寫應用的怎么能離得開CRUD?但是CRUD型接口暴露在SOA服務中往往意味着服務抽象不合理,這種類型接口帶來的不良后果:

a、鼓勵類似 RPC 的調用行為


RPC示例:

Serv.SendItemsToBePurchased(Array[] items);
Serv.ShippingAddress(stringAddress);
Serv.CheckOut();


消息示例:

//Client
string msg= "<Items>...</Items>";
MyMethod(msg);
//Server
[WebMethod]
void MyMethod(stringmsg){ . . . }


b、可能隱含帶會話狀態的交互

c、交互可能過於繁復

小結:CRUD型接口往往是抽象不合理的結果,它弱化了Contract,沒有按業務功能來實現服務。有人說CRUD可以讓調用方自己排列組合構造實現復雜服務,但是這種接口往往需要調用多次,而我們知道需要多個消息才能完成的操作是非常危險的,因為它很容易造成業務數據不一致。

 

2、數據層接口

這種服務以數據驅動,提供數據層DataTable、DataSet等重粒度的類型的返回,說到底還是抽象不合理造成的。這種接口的不良后果:

a、調用者隱性的依賴於你的服務的具體實現,結果將是緊耦合

b、Contract 沒有提供足夠的信息來使用這個服務

 

四、SOA服務設計指南

如何設計一個容易使用的、定義明確的接口?總體來說,你的接口必須:
ƒ(1)、鼓勵以文檔為中心的思考(特別提示: 如果你需要讀一些別的文檔才能調用現有接口,那你的服務分解可能不正確)
ƒ(2)、在 contract 中定義清晰的語義
ƒ(3)、通過對實現的封裝達到松耦合
ƒ(4)、可以方便的從任何平台上調用 (WS-I base profile)
ƒ(5)、用一個完整的工作單元代表一個業務流程

 

想要真正設計實現一個容易使用定義明確的接口並不容易,有幾個經驗可以指導我們的實際開發工作。

1、面向接口編程

服務接口抽象非常重要,接口抽象的同時要定義契約,定義schema,接口一旦確定以后很難修改,所以SOA接口抽象的好壞決定SOA服務的成敗。

對於一般的SOA服務,我們可以總結如下幾種類型的接口:

a、只讀(查詢)

b、只寫 (新增、修改和刪除)

c、讀和寫(CRUD的組合)

通常不論什么類型的接口,輸入參數不宜過多,參數組合或依賴關系不能過分啰嗦復雜;而對於返回信息則是越多越具體越好。

 

2、設計"大塊頭"的接口

服務必須封裝一個完全的工作單元,這種設計說明業務„系統的實現細節被封裝了,不要指望調用方排列組合CRUD型接口正確完成一個業務功能。

SOA服務需要處理失敗,在一個服務內部必須要有完善的異常處理邏輯,在任何情況下操作失敗都不會將服務留在一個不一致的狀態,不能依賴於調用者調用另一個服務來修復錯誤。

a、服務的分解

• 以業務文檔驅動的業務流程模型

• 不要試圖使服務可擴展或靈活性
b、服務的自治性

• 任何事情都不要依賴於調用者

• 預期到調用者在使用你的服務時會犯錯誤

• 永遠不要讓服務處於一種不一致的狀態

個人所接觸過的某些SOA服務在實現的過程中從來沒有考慮過接口,因為CRUD慣了,很多人認為原子的操作就是萬能的接口。


3、避免共享分布式事務
對於大塊頭接口,在一個長的流程中如何保持數據的一致性?這種情況下某些業務可能需要用到分布式事務。但是在SOA服務實現中,應該避免分布式事務,而應優先考慮Reservation (預約保留)模式或者補償機制。

Reservation 模式提供了最自治的保護,Reservation 模式的好處:

a、數據的一致性依賴於服務和它的業務規則

b、一致的處理失敗情形 (超時,通訊中斷等)
Reservation 模式的問題:

a、你必須為reservation定義業務規則 ,系統有變得更加復雜的風險

b、進度中工作項的隔離不會像二次提交的事務(2PC)那樣自動化

當然我們還可以采用補償方式,但不要依賴於調用者來完成,實在不能系統自動解決則人工介入。

 

4、保證冪等性

重復消息是SOA服務實現中非常常見的問題,你永遠不要指望調用方每次請求消息不一樣,對於讀操作,重復消息可能無害,可對於寫操作很可能就是災難。Idempotent (冪等)模式用於處理重復的消息非常合適。Idempotent (冪等)模式的基本處理思路是:

a、調用者給消息一個唯一請求 ID 標識

• 服務的Ccontract 可以說明這是必須的

• ID 標識一個工作單元,這個工作單元只應執行一次

• 工作單元ID可以是Schema的一部分,也可以是一個定制的SOAP Header

b、接收者在執行一個工作單元必須先檢驗該工作單元是否已經執行過。檢查是否執行的邏輯通常是根據唯一請求 ID ,在服務端查詢請求是否有記錄,是否有對應的響應信息,如果有,直接把響應信息查詢后返回;如果沒有,那么就當做新請求去處理。

Idempotent 模式的好處:

a、服務的自治性增強了,不需要依賴於調用者作正確的事

Idempotent 模式的缺點:

a、需要為緩存響應消耗大量的存儲空間

b、需要為緩存管理付出性能的代價

 

5、避免共享Schema

一個很常見的問題,對於多個服務,應該用同樣的 Schema還是每個服務定義自己的 Schema?

你可能會說,服務實現后就非常穩定了,應該很少改動。所以一個共享Schema搞定,維護也只維護一份,這樣不是很爽嗎?

但是,業務變化是永恆的主題,服務也需要擁抱變化。你永遠也不能保證服務實現不會變化,也不能假設每次變化共享Schema只做增量永遠向下兼容。

所以,根據實際開發和維護經驗,最合理的做法是給每個服務定義自己的 Schema(哪怕現有的Schema暫時都是一模一樣的),因為共享 Schema 使得獨立變更每個服務比較困難,並給服務的調用者帶來不必要的麻煩。

Duplicate Is Evil,但服務實現中應該避免假設適當重復,這樣應對變化才能更加游刃有余,體會到這種好處需要開發認知能力提升到一定高度。

 

6、重視性能

需求即功能,性能也是一項功能。對於開發人員,沒有人願意自己開發的接口被人說性能差。我們應該在設計時就考慮性能,在項目開發的整個過程中要對服務性能進行反復測試,循序漸進改善系統性能。
„主要有兩種量化SOA服務性能的方法:

a、機器吞吐率 (requests/sec)

b、響應時間 (time to first/last bytes)

優化服務性能的方法通常有如下幾種:

a、減少本地數據IO,盡量減少調用本地的web服務以減少網絡IO;

b、盡量使用原始數據類型參數,避免在調用之間維護服務器狀態;

c、考慮對服務的結果進行緩存;

d、要有批量多次的思路,選擇適用的大數據包傳送方式,或者對結果進行壓縮;

e、異步處理,但會增加開發和維護難度。

 

7、其他

a、避免循環調用

服務之間相互引用,或者幾個服務之間隱式地構成閉環調用,這種情況會引發無意識的遞歸造成系統崩潰。

b、重視安全性
服務調用的安全性也是一個問題。可以通過ESB實現服務注冊、角色授權、權限分配等基本安全控制,但是仍不能保證傳輸和調用安全性。可以采用一些技術解決方案增強安全性,比如微軟的WSE(Web Services Enhancements)。

 

參考:

<<SOA服務設計原則>>

<<Understanding SOA with Web Services(中文版)>>

http://www.infoq.com/cn/news/2009/09/reservations


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM