在與客戶(hù)的多次接觸中,我都需要建立一套基本的SOA原則。以下章節介紹了面向服務(wù)的架構(SOA)所需要遵循的基本準則。這些準則不是絕對正確的,只是一套針對SOA相關(guān)討論的框架性意見(jiàn)。你可能注意到前四條是基于Don Box的四項原則,只是我在經(jīng)過(guò)了這么長(cháng)時(shí)間后加上了點(diǎn)個(gè)人的想法(我之所以把它們列出來(lái)是因為有人要求我提供一個(gè)可供參考的版本;我沒(méi)有回顧過(guò)這幾條,可能現在我對其中某些的看法已有改變)
1)清晰的邊界
在調用一個(gè)服務(wù)來(lái)完成它提供的功能的時(shí)候,需要將服務(wù)所需的所有信息傳遞過(guò)去。所有對服務(wù)的訪(fǎng)問(wèn)都應通過(guò)其對外公開(kāi)的接口;不應當允許某個(gè)服務(wù)存在任何隱含的假設。:“服務(wù)不可避免地要依賴(lài)消息,因為所有進(jìn)出服務(wù)的東西都是消息”。通常情況下,服務(wù)的調用應該不依賴(lài)共享的上下文,而應該設計成無(wú)狀態(tài)的。服務(wù)所暴露的接口通過(guò)契約規定了它的功能性和非功能性的作用和特征。服務(wù)的調用是一個(gè)有業(yè)務(wù)意義的動(dòng)作,可能是十分消耗資源的,并引入一系列不同于本地調用或遠程過(guò)程的異常。服務(wù)調用是不同于普通遠程過(guò)程調用的。
提供和消費服務(wù)需要盡可能的容易,所以應當避免隱藏過(guò)多服務(wù)之間所發(fā)生的交互。服務(wù)發(fā)送和接受的消息、服務(wù)的契約以及服務(wù)本身是SOA中首先需要確立的。這里面所包含的意思,對于任何建模的語(yǔ)言和工具來(lái)說(shuō),就是起碼應該對編寫(xiě)服務(wù)的程序員提供這幾個(gè)概念方面的API.總而言之,服務(wù)通過(guò)外部接口隱藏內部細節,暴露服務(wù)的功能;于服務(wù)的交互是一個(gè)顯式的行為,它依賴(lài)服務(wù)的提供者和消費者之間消息傳遞。
2)共享契約和Schema,而不是Class類(lèi)
根據服務(wù)的描述(某種契約),服務(wù)的消費者和提供者應該擁有消費或提供服務(wù)所需要的所有東西。根據松耦合原則,服務(wù)的提供者不應該依賴(lài)消費者在它自己環(huán)境下所能提供的代碼重用能力;因為服務(wù)可能被用在不同的開(kāi)發(fā)時(shí)和運行時(shí)環(huán)境中。該原則在很大程度上限制了可以在SOA中交換的數據類(lèi)型。理想的數據格式是使用可以被一個(gè)或多個(gè)Schema所驗證的XML文檔,因為幾乎所有可以想象到的語(yǔ)言環(huán)境都支持XML.
3)策略驅動(dòng)
要跟一個(gè)服務(wù)交互,必須滿(mǎn)足兩組正交的需求:
1)服務(wù)提供者的功能、語(yǔ)法和語(yǔ)義必須滿(mǎn)足服務(wù)消費者的需求,
2)技術(shù)能力和技術(shù)需求必須相符。
打個(gè)比方,一個(gè)服務(wù)提供者可以很好地滿(mǎn)足一個(gè)服務(wù)消費者的要求,但是它是通過(guò)JMS來(lái)提供服務(wù)的,而消費者卻只能使用HTTP(例如它是在.NET平臺上實(shí)現的);提供者可能要求通過(guò)XML加密標準在消息層進(jìn)行加密,而消費者只支持SSL的傳輸層加密。即便在那些雙方都具備所需要的能力的情況下,這些能力也需要被“激活”--例如,服務(wù)提供者可能會(huì )有必要根據不同的消費者對應答消息采用不同的加密算法。
為了支持各式各樣不同設備和不同能力的服務(wù)消費者來(lái)訪(fǎng)問(wèn)服務(wù),SOA工具集必須引入某種策略機制。服務(wù)的功能性特征是由它們的接口來(lái)描述,而這些非功能性能力和需求則是用策略文件來(lái)指定的。
4)自治
跟“清晰的邊界”相關(guān)的一條準則是,一個(gè)服務(wù)應該是自治的,即,它跟外界的唯一關(guān)系(至少從SOA的角度來(lái)看)是通過(guò)它的接口。在某些情況下,一個(gè)服務(wù)還必須能夠切換它的運行期環(huán)境,例如,從輕量級的原型實(shí)現切換到完善的基于應用服務(wù)器的互相協(xié)作的多個(gè)組件的實(shí)現,而不需要用戶(hù)做任何相應的改動(dòng)。服務(wù)可以相互獨立地進(jìn)行改變、部署和版本管理。服務(wù)的提供者應該能夠不依賴(lài)用戶(hù)能力而迅速切換服務(wù)到更新的版本;而一些用戶(hù)也無(wú)法或不愿意切換到新的服務(wù)接口(特別是那些服務(wù)提供者無(wú)法控制的用戶(hù))。
5)用格式連接,而不是用程序API
服務(wù)都支持使用特定的連接格式。這條原則和“清晰的邊界”原則關(guān)系非常大,不過(guò)是引入了一個(gè)新的角度:盡最大可能讓服務(wù)可以被訪(fǎng)問(wèn)(從而達到長(cháng)期的可用性),即,只要遵循服務(wù)所定義的交互策略,應該可以從任何平臺上通過(guò)符合服務(wù)接口定義的消息的交互來(lái)訪(fǎng)問(wèn)一個(gè)服務(wù)。比如,要測試某個(gè)服務(wù)是否符合這個(gè)準則,可以看看是否能使用某種非主流的動(dòng)態(tài)編程語(yǔ)言,例如Perl,Python或Ruby來(lái)調用或提供這項服務(wù)。雖然這些語(yǔ)言在當下的技術(shù)藍圖中無(wú)足輕重,但可以作為試紙來(lái)評估服務(wù)是否滿(mǎn)足下列約束:
1)所有消息的格式使用公開(kāi)標準,或人類(lèi)可讀的描述;
2)不需要耗費很多工作就可以創(chuàng )建符合特定Schema的消息,也不需要依賴(lài)特定的程序庫;
3)正確通訊所需的額外信息(例如為了安全或可靠性所創(chuàng )建的頭部信息)的語(yǔ)義和語(yǔ)法應該依照公開(kāi)規范或標準;
4)與服務(wù)交互相關(guān)的傳輸(或傳送)協(xié)議中至少有一個(gè)是標準的網(wǎng)絡(luò )協(xié)議(或可以通過(guò)標準網(wǎng)絡(luò )協(xié)議進(jìn)行訪(fǎng)問(wèn)的);
6)面向文檔
在服務(wù)交互的時(shí)候,數據是通過(guò)文檔傳遞的。文檔是顯式建模的樹(shù)狀容器。在上面提到過(guò)的自描述性是面向文檔的一個(gè)重要特征。理想狀況下的文檔應該是按照真實(shí)世界的文檔來(lái)建模的,如采購單、發(fā)票或帳戶(hù)聲明。設計良好的文檔在特定問(wèn)題域的上下文環(huán)境中很有幫助,即它應該被一個(gè)或多個(gè)服務(wù)所采用。
類(lèi)似于真實(shí)世界的紙質(zhì)文檔,在服務(wù)中交換的文檔會(huì )包含冗余的信息。例如,客戶(hù)的地址可能與客戶(hù)的ID信息放在一起(盡管只有客戶(hù)ID就足夠了)。這些冗余的信息會(huì )被顯式的使用,它的作用在于將服務(wù)和服務(wù)消費者和服務(wù)提供者的底層數據模型進(jìn)行隔離。當使用面向文檔模式的時(shí)候,服務(wù)調用成為了有意義的業(yè)務(wù)信息交換而不僅僅是上下文無(wú)關(guān)的RPC調用。盡管沒(méi)有要求,一般都假定用XML來(lái)作為這種文檔的格式/語(yǔ)法。
消息在通過(guò)SOA互連的異構系統間的參與者之間流動(dòng)著(zhù)。松耦合原則要求對于共有認知的依賴(lài)越小越好。當消息在分布式對象或RPC環(huán)境中傳遞時(shí),客戶(hù)端和服務(wù)端依賴(lài)的是一組用同一個(gè)接口描述文檔自動(dòng)生成的代理類(lèi)(stubs和skeletons)。如果不采用這樣的方式,若契約本身不支持雙方交互則將無(wú)法通訊。所以說(shuō),RPC形式的架構必然要求客戶(hù)端和服務(wù)端代碼同步變化。
通過(guò)下面的比較我們來(lái)看一看??紤]以下消息:
“2006-03-1347113”
將它和
<order />
<date />2006-03-13</date />
<product />4711</product />
<quantity />3</quantity />
</order />
比較一下。
顯然后者比前者的可讀性更好,并且對于后者來(lái)說(shuō),除了使用固定的語(yǔ)法,參與者還可以使用例如XPath這樣的技術(shù)來(lái)隔離細微的非顛覆性的變化。反過(guò)來(lái)說(shuō),如果用了像XML這樣的自描述格式的消息卻仍然使用RPC方式進(jìn)行通訊,其作用無(wú)非只能證明XML是最消耗帶寬的一種方式。如果你使用XML,那么一定要利用它的優(yōu)點(diǎn)而不是缺點(diǎn)。
7)松耦合
大多數SOA倡導者都認同松耦合是一個(gè)重要的概念。但不幸的是,對于一個(gè)系統“松耦合”特性的認定卻有很多不同的選項。認定一個(gè)系統是松耦合還是緊耦合的,根據具體的需求和上下文可以有許多維度,從某些維度來(lái)看可能是松耦合,但是從另一些維度來(lái)看又可能那是緊耦合。這些維度包括:
時(shí)間:當(服務(wù))參與者在時(shí)間維度上松耦合時(shí),他們不是必須同時(shí)在線(xiàn)才能進(jìn)行交互。這要求他們之間必須有某種緩沖和隊列的機制。當一個(gè)參與者發(fā)送消息到對方的時(shí)候,它不必依賴(lài)立即的消息回復也能繼續流程。
位置:如果參與者需要知道其它參與者的位置信息來(lái)進(jìn)行通訊,那么位置的松耦合意味著(zhù)當這些位置信息的改變時(shí)應該不需要重新編程、重新配置或重新啟動(dòng)通訊中的各個(gè)參與者。這就隱含要求了服務(wù)的調用需要有一個(gè)尋址過(guò)程,并需要某種目錄或地址簿存儲服務(wù)終端的位置。
類(lèi)型:類(lèi)似編程語(yǔ)言中的靜態(tài)類(lèi)型/動(dòng)態(tài)類(lèi)型或強類(lèi)型/弱類(lèi)型,類(lèi)型的松耦合使得服務(wù)的參與者不依賴(lài)文檔的全部或哪怕部分結構。
版本:服務(wù)的參與者可能依賴(lài)特定版本的服務(wù)接口,也可能可以接口接口的(一定程度上)變化。越是依賴(lài)服務(wù)的特定版本,參與者的松耦合的程度就越低(在該維度上)。一個(gè)不錯的參考準則是Postel法則:服務(wù)提供者的實(shí)現應當盡可能接受各種版本,以擁有更大的自由度(甚至可以容錯),而服務(wù)的消費者則應該盡可能地遵循特定的語(yǔ)法和文檔接口。這樣可以增加系統整體上的可靠性和靈活性。
關(guān)聯(lián):在某些情況下,服務(wù)消費者和服務(wù)提供者之間是1:1的關(guān)系,尤其是在“請求-答復”式交互或使用顯式的消息隊列的情況下。而在另外一些情況中,服務(wù)的消費者(叫“消息發(fā)送者”或“事件源”更合適)可能不知道甚至根本不在乎收到的消息數。
查詢(xún):請求服務(wù)調用的參與者既可以根據服務(wù)提供者的(物理的或邏輯的)名字來(lái)跟它們通訊,也可以首先根據一組能力描述執行一個(gè)服務(wù)查找操作。這意味著(zhù)需要有一個(gè)可以將消費者需求和服務(wù)提供者能力進(jìn)行匹配的服務(wù)注冊表或服務(wù)倉庫。
接口:既可以要求參與者依賴(lài)服務(wù)所提供的特定接口,也可以要求它們支持一個(gè)通用的接口。如果使用通用接口,所有使用這個(gè)通用接口的參與者就可以和所有提供這個(gè)通用接口的參與者進(jìn)行交互。盡管乍一看這樣做非常別扭,但這種單一(統一)通用接口卻是WWW結構中的核心所在。
任何創(chuàng )建的系統不可能、也不需要滿(mǎn)足上述所有維度的松耦合。對于不同類(lèi)型的服務(wù)需要做不同程度的權衡。
8)兼容工業(yè)標準
在準備實(shí)施SOA的時(shí)候一條關(guān)鍵的原則就是依賴(lài)標準而不是依賴(lài)特定的API。從技術(shù)層面上來(lái)說(shuō),標準包括數據格式、元信息、傳輸協(xié)議、以及業(yè)務(wù)級別的文檔格式(如UBL)。
9)廠(chǎng)商無(wú)關(guān)
在任何架構準則中,都不應該依賴(lài)某個(gè)特定廠(chǎng)商的產(chǎn)品。在將抽象概念轉化到實(shí)際可運行的系統的過(guò)程中,不可避免地要選用某個(gè)特定的產(chǎn)品,不論是商業(yè)的或開(kāi)源的軟件。但是不應該在架構一級上就先入為主地考慮到這些決定。這就是說(shuō)要盡量考慮到標準的互可操作性和可移植性。這樣一來(lái),參與者可以使用支持標準的任何技術(shù)來(lái)構建,而不用受制于廠(chǎng)商的產(chǎn)品路線(xiàn)。
10)元數據驅動(dòng)在整個(gè)SOA架構中,所有的元信息必須以恰當的方式存儲在某個(gè)地方,使得它們可以同時(shí)在設計時(shí)和運行時(shí)被發(fā)現、獲取和解釋。這些元信息包括服務(wù)接口的描述、參與者、服務(wù)終端(endpoint)、綁定信息(bingdings)、組織的結構和職責、文檔類(lèi)型和schema、消費者-提供者關(guān)系,等等。這些元信息的使用應該利用代碼生成或解釋的方式盡可能地自動(dòng)化,并成為服務(wù)和參與者生命周期中的一部分。
作者簡(jiǎn)介:黃凱,上海普元軟件公司資深架構師。應用數學(xué)系學(xué)士,軟件工程學(xué)碩士,獲得系統分析員認證。曾參與EOS構件中間件的Studio和Server的核心架構設計。在Eclipse插件開(kāi)發(fā)、SOA設計實(shí)現、Struts/Spring/Webwork/Hibernate等框架技術(shù)以及ANTLR, LUCENE等方面有很多經(jīng)驗和深入研究。
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請
點(diǎn)擊舉報。