微觀SOA:服務設計原則及其實踐方式(上篇)
大量互聯網公司都在擁抱SOA和服務化,但業界對SOA的很多討論都比較偏向高大上。本文試圖從稍微不同的角度,以相對接地氣的方式來討論SOA,集中討論SOA在微觀實踐層面中的緣起、本質和具體操作方式,另外也用相當篇幅介紹了當今互聯網行業中各種流行的遠程調用技術等等,比較適合從事實際工作的架構師和程序員來閱讀。
為了方便閱讀,本話題將分為兩篇展現。本文是上篇,著眼于微觀SOA的定義,并簡單分析其核心原則。
亞馬遜CEO杰夫·貝佐斯:鮮為人知的SOA大師
由于SOA有相當的難度和門檻,不妨先從一個小故事說起,從中可以管窺一點SOA的大意和作用。
按照亞馬遜前著名員工Steve Yegge著名的“酒后吐槽”,2002年左右,CEO貝佐斯就在亞馬遜強制推行了以下六個原則(摘自酷殼):
- 所有團隊的程序模塊都要以通過Service Interface 方式將其數據與功能開放出來。
- 團隊間的程序模塊的信息通信,都要通過這些接口。
- 除此之外沒有其它的通信方式。其他形式一概不允許:不能使用直接鏈結程序、不能直接讀取其他團隊的數據庫、不能使用共享內存模式、不能使用別人模塊的后門、等等,等等,唯一允許的通信方式只能是能過調用 Service Interface。
- 任何技術都可以使用。比如:HTTP、Corba、Pubsub、自定義的網絡協議、等等,都可以,貝佐斯不管這些。
- 所有的Service Interface,毫無例外,都必須從骨子里到表面上設計成能對外界開放的。也就是說,團隊必須做好規劃與設計,以便未來把接口開放給全世界的程序員,沒有任何例外。
- 不這樣的做的人會被炒魷魚。
據說,亞馬遜網站展示一個產品明細的頁面,可能要調用200-300個Service,以便生成高度個性化的內容。
Steve還提到:
Amazon已經把文化轉變成了“一切以Service第一”為系統架構的公司,今天,這已經成為他們進行所有設計時的基礎,包括那些絕不會被外界所知的僅在內部使用的功能。
那時,如果沒有被解雇的的恐懼他們一定不會去做。我是說,他們今天仍然怕被解雇,因為這基本上是那兒每天的生活,為那恐怖的海盜頭子貝佐斯工作。不過,他們這么做的確是因為他們已經相信Service這就是正確的方向。他們對于SOA的優點和缺點沒有疑問,某些缺點還很大,也不疑問。但總的來說,這是正確的,因為,SOA驅動出來的設計會產生出平臺(Platform)。
今天,我們都知道亞馬遜從世界上最大圖書賣場進化為了世界上最成功的云平臺……
貝佐斯的六原則展示出高度的遠見和超強的信念,即使放到十幾年后的今天,依然覺得振聾發聵……想起一句老話:“不謀萬世者,不足以謀一時;不謀全局者,不足以謀一隅。”
當然,像貝佐斯這種將神性與魔性集于一身的專橫人物,既可能創造劃時代的進步,也可能制造前所未有的災難。
SOA漫談:宏觀與微觀
SOA即面向服務架構,是一個特別大的話題。
為了方便討論,我在此先草率的將SOA分為兩個層面(大概模仿宏觀和微觀經濟學,但這里的劃分沒有絕對界限):
- 宏觀SOA:面向高層次的部門級別、公司級別甚至行業級別;涉及商業、管理、技術等方面的綜合的、全局的考慮;架構體系上包括服務治理(governance,如服務注冊,服務監控),服務編排(orchestration,如BPM,ESB),服務協同(choreography,更多面向跨企業集成)等等。我認為SOA本身最主要是面向宏觀層面的架構,其帶來益處也最能在宏觀高層次上體現出來,同時大部分SOA的業界討論也集中在這方面。
- 微觀SOA:面向有限的、局部的團隊和個人;涉及獨立的、具體的服務在業務、架構、開發上的考慮。
很多業界專家都認為SOA概念過于抽象,不接地氣,我認為主要是宏觀SOA涉及面太廣,經常需要做通盤考慮,而其中很多方面距離一般人又比較遠。而在微觀層面的SOA更容易達到濤哥過去提出的“三貼近”:貼近實際、貼近生活、貼近群眾。
同時,宏觀SOA要取得成功,通常的前提也是SOA在微觀層面的落地與落實,正如宏觀經濟學一般要有堅實的微觀基礎(比如大名鼎鼎的凱恩斯主義曾廣受詬病的一點就是缺乏微觀基礎)
因此,我們著眼于SOA落地的目的,著重來分析微觀SOA,也算是對業界主流探討的一個小小的補充。
SOA定義
按照英文維基百科定義:SOA是一種“軟件”和“軟件架構”的設計模式(或者叫設計原則)。它是基于相互獨立的軟件片段要將自身的功能通過“服務”提供給其他應用。
什么是“服務”?按照OASIS的定義:Service是一種按照既定“接口“來訪問一個或多個軟件功能的機制(另外這種訪問要符合“服務描述”中策略和限制)
Service示例(代碼通常以java示例)
public interface Echo { String echo(String text); } public class EchoImpl implements Echo { public String echo(String text) { return text; } }
可能每個開發人員每天都在寫類似的面向對象的Service,難道這就是在實施SOA嗎?
SOA設計原則
既然SOA是設計原則(模式),那么它包含哪些內容呢?事實上,這方面并沒有最標準的答案,多數是遵從著名SOA專家Thomas Erl的歸納:
標準化的服務契約 Standardized service contract 服務的松耦合 Service loose coupling 服務的抽象 Service abstraction 服務的可重用性 Service reusability 服務的自治性 Service autonomy 服務的無狀態性 Service statelessness 服務的可發現性 Service discoverability 服務的可組合性 Service composability ....
這些原則總的來說要達到的目的是:提高軟件的重用性,減少開發和維護的成本,最終增加一個公司業務的敏捷度。
但是,業界著名專家如Don Box,David Orchard等人對SOA又有各自不同的總結和側重。
SOA不但沒有絕對統一的原則,而且很多原則本身的內容也具備相當模糊性和寬泛性:例如,所謂松耦合原則需要松散到什么程度才算是符合標準的呢?這就好比一個人要帥到什么程度才算是帥哥呢?一棟樓要高到多少米才算是高樓呢?可能不同人心中都有自己的一桿秤……部分由于這些理論上的不確定因素,不同的人理解或者實施的SOA事實上也可能有比較大的差別。
淺析松耦合原則
SOA原則比較多,真正的理解往往需要逐步的積累和體會,所以在此不詳細展開。這里僅以服務的松耦合為例,從不同維度來簡單剖析一下這個原則,以說明SOA原則內涵的豐富性:
-
實現的松耦合:這是最基本的松耦合,即服務消費端不需要依賴服務契約的某個特定實現,這樣服務提供端的內部變更就不會影響到消費端,而且消費端未來還可以自由切換到該契約的其他提供方。
-
時間的松耦合:典型就是異步消息隊列系統,由于有中介者(broker),所以生產者和消費者不必在同一時間都保持可用性以及相同的吞吐量,而且生產者也不需要馬上等到回復。
-
位置的松耦合:典型就是服務注冊中心和企業服務總線(ESB),消費端完全不需要直接知道提供端的具體位置,而都通過注冊中心來查找或者服務總線來路由。
-
版本的松耦合:消費端不需要依賴服務契約的某個特定版本來工作,這就要求服務的契約在升級時要盡可能的提供向下兼容性。
SOA與傳統軟件設計
我們可以認為:SOA ≈ 模塊化開發 + 分布式計算
將兩者傳統上的最佳實踐結合在一起,基本上可以推導出SOA的多數設計原則。SOA從軟件設計(暫不考慮業務架構之類)上來講,自身的新東西其實不算很多。
SOA原則的應用
基于SOA的原則,也許我們很難說什么應用是絕對符合SOA的,但是卻能剔除明顯不符合SOA的應用。
用上述標準化契約,松耦合和可重用這幾個原則來嘗試分析一下上面Echo示例:
-
Echo的服務契約是用Java接口定義,而不是一種與平臺和語言無關的標準化協議,如WSDL,CORBA IDL。當然可以抬杠,Java也是行業標準,甚至全國牙防組一致認定的東西也是行業標準。
-
Java接口大大加重了與Service客戶端的耦合度,即要求客戶端必須也是Java,或者JVM上的動態語言(如Groovy、Jython)等等……
-
同時,Echo是一個Java的本地接口,就要求調用者最好在同一個JVM進程之內……
-
Echo的業務邏輯雖然簡單獨立,但以上技術方面的局限就導致它無法以后在其他場合被輕易重用,比如分布式環境,異構平臺等等。
因此,我們可以認為Echo并不太符合SOA的基本設計原則。
透明化的轉向SOA?
修改一下上面的Echo,添加Java EE的@WebServices注解(annotation)
@WebServices public class EchoImpl implements Echo { public String echo(String text) { return text; } }
現在將Echo發布為Java WebServices,并由底層框架自動生成WSDL來作為標準化的服務契約,這樣就能與遠程的各種語言和平臺互操作了,較好的解決了上面提到的松耦合和可重用的問題。按照一般的理解,Echo似乎就成為比較理想的SOA service了。
但是……即使這個極端簡化的例子,也會引出不少很關鍵的問題,它們決定SOA設計開發的某些難度:
- 將一個普通的Java對象通過添加注解“透明的”變成WebServices就完成了從面向對象到面向服務的跨越?
- 通過Java接口生成WSDL服務契約是好的方式嗎?
- WebServices是最合適遠程訪問技術嗎?
面向對象和面向服務的對比
面向對象(OO)和面向服務(SO)在基礎理念上有大量共通之處,比如都盡可能追求抽象、封裝和低耦合。
但SO相對于OO,又有非常不同的典型應用場景,比如:
-
多數OO接口(interface)都只被有限的人使用(比如團隊和部門內),而SO接口(或者叫契約)一般來說都不應該對使用者的范圍作出太多的限定和假設(可以是不同部門,不同企業,不同國家)。還記得貝佐斯原則嗎?“團隊必須做好規劃與設計,以便未來把接口開放給全世界的程序員,沒有任何例外”。
-
多數OO接口都只在進程內被訪問,而SO接口通常都是被遠程調用。
簡單講,就是SO接口使用范圍比一般OO接口可能廣泛得多。我們用網站打個比方:一個大型網站的web界面就是它整個系統入口點和邊界,可能要面對全世界的訪問者(所以經常會做國際化之類的工作),而系統內部傳統的OO接口和程序則被隱藏在web界面之后,只被內部較小范圍使用。而理想的SO接口和web界面一樣,也是變成系統入口和邊界,可能要對全世界開發者開放,因此SO在設計開發之中與OO相比其實會有很多不同。
小結
在前述比較抽象的SOA大原則的基礎上,我們可嘗試推導一些較細化和可操作的原則,在具體實踐中體現SO的獨特之處。請關注本系列文章的下篇!