談SOA服務的設計粒度
先談幾點個人體會
- 業務服務如果是是否存在可重用的原子服務,如果有則應該先做原子服務再做組合服務。
- 原子服務存在的意義在于存在多個業務服務復用,如果不存在不識別為原子服務。
- 從業務出發,為了保證事物完整性和服務設計的無狀態原則,應該如何設計,哪些能拆,哪些不能拆。
- 根據BPEL流程編排,會增加業務校驗類細粒度服務,應從滿足多個業務編排需求來考慮可重用性。
- 根據安全性原則,哪些服務需要拆分,根據拆分服務提供不同屬性類別的服務
- 根據性能原則,哪些粗粒度服務當不滿足性能測試要求時候需要拆分為多個細粒度的服務
另外關于服務顆粒度的問題,可以看百度百科的說明。
什么是服務的顆粒度?一般的說法,服務顆粒度(servicegranularity)就是指一個服務包含的功能大小。舉個例子,對于電信九七系統中的營業受理來說,提交客戶訂單就是一個典型的粗粒度的服務,而實現這個提交訂單服務的一系列內部操作,比如說創建客戶資料,生成客戶訂單,記錄產品屬性,更新帳務關系等等就可能成為一系列細粒度的服務。細粒度的服務(fine-grained)提供相對較小的功能單元,或交換少量的數據。完成復雜的業務邏輯往往需要編排大量這種細粒度的服務,通過多次的服務請求交互才能實現。相反,粗粒度的服務(coarse-grained)則是在一個抽象的接口中封裝了大塊的業務/技術能力,減少服務請求交互的次數,但相應也會帶來服務實現的復雜性,交互大量的數據,并因此而不能靈活更改以適應需求的變化。就像任何事物都有兩面性一樣,服務粒度不能太大或者太小,而應該大小合適。一個良好的SOA架構設計,必須在服務粒度設計上維護一種平衡,以獲得成本降低,靈活響應的好處。
盡管沒有一本Bible讓我們可以依此正確地設計服務的粒度,但我們還是能從與之相關的多方面利弊權衡的設計實踐中,總結出一些能夠幫助正確選擇服務顆粒度的經驗法則。識別并設計一個粒度適中的服務,我們可以主要從以下三個方面權衡考量。
x重用性
所謂重用性,就是指服務能夠應用于不同上下文的能力。重用可以說是SOA的核心思維,通過重用獲得降低開發維護成本,縮短應用交付周期,提升質量等種種好處。
與任何基于分解的范例相一致,顆粒度的大小直接影響到服務的可重用性。一個簡單的經驗法則就是細粒度的服務更容易被重用。換句話說,就是顆粒度越粗,服務越少被重用或者越難以被重用。因為隨著顆粒度增加,越來越多的業務規則和上下文信息被嵌入到業務邏輯中,服務逐漸變得具有特定的業務意義。要使用它,我們必須首先了解它到底封裝了哪些規則,否則我們無法確信這個服務正是我們所需要的。這并不意味著我們就不要構建粗粒度的服務,事實上粗粒度的服務往往還停留在”business-grained”層面,它讓業務用戶和IT人員可以直接對話,對業務有直接的意義,應該暴露出來。同時,如果我們僅僅機械地考慮重用性,將導致大量顆粒度很小的功能單元,這將對系統整體性能和容量帶來嚴重的影響。就拿大家常用來描繪SOA的樂高玩具為喻,一個最小尺寸的1x1的樂高積木,帶有一個標準的凸起接口,通過它幾乎可以與任何其它樂高積木拼裝出任意可以想想的物體,其廣泛的重用性是不言而喻的。但是當你真正嘗試用這種粒度的積木完成一個復雜物體拼裝的時候,你可能會感嘆:“Oh,My God! It’s missionimpossible!”,因為,為此付出的時間和成本的代價幾乎是不可接受的。因此,我們在一心希望構建美好的重用世界之前,需要先掂量清楚服務顆粒度的選擇。
在這里,我借用關于演講的一個有名的“迷你裙定律”來嘗試表達服務顆粒度的選擇上的權衡之道。“mini-skirttheory”告訴我們,一個出色的演講應該“short enough to keep people interested, butlong enough to cover the importantpart”。套用在服務顆粒度的選擇上,一個設計良好的服務應該“fine-grained enough to be reusable,but coarse-grained enough to make business sense”。
x靈活性
所謂靈活性,就是能夠容易地因情形做出改變的能力。SOA的目標之一就是讓IT變得更靈活,能夠更快地適應持續變化的業務環境。因此,靈活性作為設計良好的服務的重要考量,理所當然地也是選擇服務粒度的重要標準之一。眾所周知,細粒度的服務可以更容易地組裝,為交付新的業務功能或改變業務流程提供了更多的靈活性。但是,僅僅考慮靈活性將導致大量的細粒度的服務,帶來昂貴的開發成本,并使得維護變得困難。因此,在考慮業務流程靈活性的同時,考慮后臺服務的良好組織、效率和開發維護成本,對于識別和設計粒度適中的服務是至關重要的。
我們知道,服務識別方法之一就是top-down的一級級流程分解,直到不能或者不需要進一步分解為止,其中識別出來的的業務活動就是候選的業務服務。因此,一個有效的經驗法則就是區別對待不同的業務流程,因為并不是每一個業務流程都需要相同的靈活性。如何確定哪些流程需要更多的靈活性,哪些流程不需要,可以參考SAP就企業業務流程的一個觀點。SAP將流程劃分為核心流程(coreprocess)和支撐流程(contextprocess)。其中,支撐流程是指那些不可或缺的,但又不影響企業差異化的流程,如財會管理流程等,它們關注的是如何提升生產效率,降低生產成本。因此這些流程在分解過程中,一旦識別出自治的(事務一致、上下文獨立的)、粗粒度的服務就可以結束,因為它們相對穩定。而核心流程是指企業獨特的,差異化的,代表企業競爭力的業務流程,如營銷銷售流程等。它們需要比支撐流程更細粒度地分解,以獲得最大的靈活性,因為它們是時刻變化的。
x性能
靈活性和效率往往是成對出現的,性能因素自然也是限制服務粒度不能太大或者太小的約束之一。 DanFoody曾在他的weblog里建議Webservice的每一個operation執行應該在5ms到5s之間完成,小于5ms或者大于5s就意味著服務粒度要么太小,要么太大。我在這里倒不想評價這個量化的指標有多大指導意義,而是借此希望引起大家的思考,并不是服務粒度越小或者越大,系統性能就會一定越好。
一個服務本身的復雜度以及業務到服務映射的復雜度(即實現一個業務活動所需的服務調用次數)是影響SOA性能的兩個主要方面。服務顆粒度越大,意味著包含的功能越多,業務邏輯越復雜,網絡延遲就會增加,對客戶端響應變慢。而服務顆粒度越小,也就意味著包含的功能越簡單,雖然單個服務執行效率很高,但從業務意義上,完成一項業務任務所需的服務調用次數越多,來回請求響應次數增加。一般來說,服務都是遠程調用的,這種來回請求響應的次數增加意味著顯著的性能開銷。因此,為了保證服務的性能可控,一方面需要限制服務包含的功能范圍和復雜度,也就是說服務粒度不能太粗;另一方面需要限制服務調用的次數和復雜度,也就是說服務粒度不能太細。我想這才是前面提到的5ms和5s背后真正的原因。很顯然,二者的著眼點是背離的,為了符合性能的需求,需要在二者之間折中妥協。
除以上幾點之外,還存在其它可能影響服務顆粒度決策的因素,比如服務類別和使用范圍等等。如果服務使用的范圍有限,如僅僅在Intra-Application范疇,則可以選擇相對較細粒度的服務接口,為服務請求者提供更多的靈活性;隨著范圍擴大,服務大小也應隨之擴大,如Multi-Enterprise的范疇,則要求服務盡可能提供粗粒度的、較穩定的接口,保證服務請求者以一致的方式使用系統中所暴露出的服務。最后,需要記住的一點是,服務的顆粒度在其生命周期內不是一成不變的,它是隨著業務的調整變化,以及服務的迭代發展過程,不斷演化精煉、甚至重構的。