摘要:在企業(yè)應(yīng)用集成的發(fā)展進(jìn)程中,組件扮演著十分重要的角色。組件類型的多樣性使得不同類型組件的集成工作面臨很大的困難,如何對(duì)不同的組件在合理規(guī)劃的基礎(chǔ)上進(jìn)行統(tǒng)一管理,一直以來(lái)都是軟件設(shè)計(jì)師們研究的熱點(diǎn)。通過(guò)分析不同類型組件的特征,提出了將遠(yuǎn)程組件本地化的思想,并基于此思想設(shè)計(jì)了服務(wù)訪問(wèn)代理以及一個(gè)基于元數(shù)據(jù)的組件容器,在設(shè)計(jì)過(guò)程中運(yùn)用了多種設(shè)計(jì)模式,以使其更加高效。
關(guān)鍵詞:企業(yè)應(yīng)用集成;組件;本地化;組件容器;設(shè)計(jì)模式
中圖分類號(hào):TP302文獻(xiàn)標(biāo)識(shí)碼:A文章編號(hào):1009-3044(2008)28-0105-02
Research on Component Integration Based on Service Access Proxy
BIAN Xiao-fan1, ZHAO Feng2
(1.Computer Center,Hebei University,Baoding 071002,China;2.College of Math and Computer,Hebei University,Baoding 071002,China)
Abstract: Component has played a key role during the process of Enterprise Application Integration (EAI). The diversity of components makes it a tough work to integrate components of different types, and software architects has been always focusing on the issue that how to mange different components in a uniform way based on an reasonable design. Through analyzing the component's attributes of different types, a thought of localizing the remote components was brought up, a service access proxy and a component container based on a metadata engine was designed on the basis of this thought, and lots of design patterns are applied to make it more effective.
Key words: EAI; component; localize; component container; design pattern
1 引言
在企業(yè)信息化的廣泛發(fā)展及不斷深化的過(guò)程中,企業(yè)應(yīng)用集成技術(shù)發(fā)揮了重大作用。SOA(Service Oriented Architecture)的迅速發(fā)展及廣泛應(yīng)用,促使了基于SOA的EAI的產(chǎn)生。在此大環(huán)境下,整個(gè)企業(yè)的所有系統(tǒng)都被視為一個(gè)個(gè)松散結(jié)構(gòu)中的組件,系統(tǒng)接口、組件之間的通信、數(shù)據(jù)格式及轉(zhuǎn)換和組件目錄信息都應(yīng)建立在開(kāi)放、統(tǒng)一的標(biāo)準(zhǔn)之上,使得集成后的系統(tǒng)具有開(kāi)放性、可擴(kuò)充性等特點(diǎn)。
然而,在良好的分布式架構(gòu)模式下,仍然存在一些性能和效率上的問(wèn)題。在集成過(guò)程中,企業(yè)遺留系統(tǒng)往往被當(dāng)作一個(gè)組件或服務(wù)發(fā)布,并通過(guò)RPC(遠(yuǎn)程過(guò)程調(diào)用)的方式被應(yīng)用系統(tǒng)調(diào)用或訪問(wèn)。在一個(gè)大型的應(yīng)用中可能要用到多種組件類型,有的以Web服務(wù)形式發(fā)布,也有的通過(guò)RMI、Hessian、HttpInvoker等技術(shù)發(fā)布。面對(duì)如此繁雜的組件類型,如果不提供一種合理的方式對(duì)它們進(jìn)行統(tǒng)一管理,勢(shì)必會(huì)造成組件訪問(wèn)方式的混亂,并最終影響系統(tǒng)的開(kāi)發(fā)及運(yùn)行效率。本文將從一個(gè)新的角度提出一種新的解決方案來(lái)優(yōu)化組件的管理策略以及訪問(wèn)性能。
2 設(shè)計(jì)思想
為了滿足快速搭建大型分布式應(yīng)用的需要,除了編寫(xiě)大量的本地組件以外,還要考慮將企業(yè)原有信息系統(tǒng)集成進(jìn)來(lái),從而極大的加速新系統(tǒng)的開(kāi)發(fā)進(jìn)程。然而我們又不得不面臨多類型組件混用帶來(lái)的設(shè)計(jì)上的復(fù)雜性。一個(gè)業(yè)務(wù)流程通常要借助多個(gè)組件的協(xié)作來(lái)完成,如果不對(duì)組件的獲取及調(diào)用進(jìn)行統(tǒng)一管理,那么就不可避免的要在業(yè)務(wù)代碼中穿插很多組件訪問(wèn)代碼,而且訪問(wèn)方式各不相同,不但代碼可讀性差,而且給后期的維護(hù)埋下了巨大的隱患。
針對(duì)這一問(wèn)題,有許多可供選擇的解決方案。一種普遍的做法是統(tǒng)一組件的發(fā)布方式,即將所有類型的組件以Web服務(wù)形式發(fā)布。這樣可以統(tǒng)一組件的獲取及調(diào)用方式,但是此方法的缺陷也是很明顯的。Web服務(wù)的通信是以SOAP為通信協(xié)議的,并以HTTP或SMPT為信息載體,對(duì)于絕大多數(shù)原本可直接訪問(wèn)的本地組件,若都經(jīng)過(guò)這樣一道程序,在訪問(wèn)效率上自然就大打折扣。
綜合以上的分析,本文提出了在保持本地組件不變的基礎(chǔ)上,對(duì)遠(yuǎn)程服務(wù)進(jìn)行重構(gòu),并通過(guò)添加服務(wù)訪問(wèn)代理的方式將其本地化,并通過(guò)一個(gè)基于元數(shù)據(jù)的組件容器對(duì)所有組件進(jìn)行統(tǒng)一管理。該設(shè)計(jì)方案的總體架構(gòu)如圖1所示。
圖1虛線框內(nèi)為本架構(gòu)的核心部分,主要由服務(wù)訪問(wèn)代理和組件容器構(gòu)成。其中,服務(wù)訪問(wèn)代理負(fù)責(zé)對(duì)遠(yuǎn)程的各種服務(wù)進(jìn)行封裝,使其具有本地組件的特點(diǎn)。組件容器除了接收本地的組件,同樣也容納經(jīng)服務(wù)訪問(wèn)代理封裝后的代理組件,并對(duì)其管轄范圍內(nèi)的組件的生命周期進(jìn)行有效管理。另外,組件容器還要向應(yīng)用程序提供統(tǒng)一的訪問(wèn)接口,方便應(yīng)用程序以唯一的方式調(diào)用組件。
3 詳細(xì)設(shè)計(jì)方案
3.1 遠(yuǎn)程服務(wù)本地化思想
遠(yuǎn)程服務(wù)本地化,即將遠(yuǎn)程服務(wù)改裝成本地組件,使原先對(duì)遠(yuǎn)程服務(wù)的操作變得如同訪問(wèn)本地組件一樣簡(jiǎn)便。為了達(dá)到這一目的,需要對(duì)遠(yuǎn)程服務(wù)訪問(wèn)代碼進(jìn)行封裝,從而簡(jiǎn)化遠(yuǎn)程服務(wù)的獲取方式。這樣做最大的好處是屏蔽掉了各種遠(yuǎn)程調(diào)用技術(shù)之間的差異,使不熟悉RPC方式的開(kāi)發(fā)人員同樣可以參加到團(tuán)隊(duì)合作中來(lái),不但加快了開(kāi)發(fā)進(jìn)程,同時(shí)也縮減了培訓(xùn)的開(kāi)支。本文是以添加服務(wù)訪問(wèn)代理的方式解決了遠(yuǎn)程服務(wù)的本地化問(wèn)題,并通過(guò)組件容器來(lái)最終實(shí)現(xiàn)遠(yuǎn)程服務(wù)與本地組件的集成。
3.2 服務(wù)訪問(wèn)代理
服務(wù)訪問(wèn)代理主要完成兩個(gè)方面的工作。一方面是封裝遠(yuǎn)程服務(wù)訪問(wèn)代碼,另一方面是使其具有本地組件的一般形式,便于組件容器的識(shí)別以及統(tǒng)一管理。具體的做法我們參考了GoF的代理模式[2] ,對(duì)于每一個(gè)非本地組件,都在本地維護(hù)一個(gè)與其相對(duì)應(yīng)訪問(wèn)代理類。此代理類將與原組件擁有相同的方法或函數(shù),只不過(guò)在方法體內(nèi)的不是方法的具體實(shí)現(xiàn),而是方法的調(diào)用代碼,從而完成遠(yuǎn)程組件的本地化。實(shí)現(xiàn)過(guò)程可簡(jiǎn)可繁,既可采取手工方式,也可以編寫(xiě)一個(gè)工具來(lái)替你完成轉(zhuǎn)換工作,當(dāng)然后者在前期工作量較大,但卻可以達(dá)到一勞永逸的效果。我們稱被代理后的遠(yuǎn)程服務(wù)為代理組件,代理組件將與本地組件一同納入組件容器之中實(shí)行統(tǒng)一調(diào)度。
3.3 組件容器設(shè)計(jì)
組件容器的設(shè)置主要是對(duì)組件的生成、初始化、單例控制、銷毀等生命周期活動(dòng)進(jìn)行更有效的管理,并向應(yīng)用程序提供統(tǒng)一的調(diào)用接口。在組件容器的設(shè)計(jì)過(guò)程中,我們利用元數(shù)據(jù)的平臺(tái)無(wú)關(guān)性[5],實(shí)現(xiàn)了組件的插件化管理,極大地減輕了后期維護(hù)的壓力,并保證了先期工作的效用最大化。組件容器的邏輯架構(gòu)圖如圖2所示。
由圖2可知,組件容器大致由兩部分組成:元數(shù)據(jù)引擎和組件工廠,各部分功能詳述如下。
3.3.1元數(shù)據(jù)引擎部分
圖2中標(biāo)注五角星的文件是組件配置文檔,它是該引擎的核心,其它一系列的輔助功能都是圍繞它展開(kāi)的。各部分的功能及實(shí)現(xiàn)簡(jiǎn)述如下:
1) 組件配置文檔應(yīng)包含所供述組件的所有信息,并應(yīng)具備可讀,和易解析的特點(diǎn)。XML作為W3C的一個(gè)標(biāo)準(zhǔn),具有很強(qiáng)的通用性和很高的理論成熟度,并且有很多可供選擇的支持工具,所以理所應(yīng)當(dāng)?shù)乇贿x做本引擎的元數(shù)據(jù)載體。組件配置文檔的基本配置信息如下所示:
<component_list>
<cp id=\"cpProxy\" class=\"namespace.CpProxy\" singleton=\"true\">
<constructor>
<arg0 type=\"STRING\" value=\"arg0\"/>
<arg1 type=\"BYTE\" value=\"arg1\"/>
<!-- 其它參數(shù) -->
<constructor/>
<setters>
<setter property=\"product\" type=\"STRING\">some_product</setter>
<setter property=\"amount\" type=\"INTEGER\">40</setter>
<!-- 其它setter -->
</setters>
</cp>
<!-- 其它組件配置 -->
</component_list>
配置信息的根元素為component_list,它代表了一個(gè)組件列表。cp則描述了一個(gè)具體的組件配置,id作為一個(gè)區(qū)別于其它組件的唯一性標(biāo)志,而class則指明了該組件的代理類,后面的singleton可作為一個(gè)可選屬性,表征組件是否在系統(tǒng)運(yùn)行過(guò)程中只保持有一個(gè)實(shí)例,參照了GoF的單例模式。constructor和setter分別代表組件類的構(gòu)造函數(shù)和set方法,是為提供IOC支持而設(shè)置的。
IOC(Inversion of Control)控制反轉(zhuǎn),又叫依賴注入[8],基本思想就是把對(duì)象的生命周期、依賴關(guān)系等交由容器來(lái)管理,而不是直接在應(yīng)用中編程管理。通常IOC的實(shí)現(xiàn)有三種方式,本實(shí)例提供構(gòu)造函數(shù)注入和設(shè)值注入兩種IOC方式供開(kāi)發(fā)者選擇。
2) XML Schema又稱作XML Schema Definition(XSD),同樣是W3C的一個(gè)標(biāo)準(zhǔn),它的作用是對(duì)XML的格式進(jìn)行定義。在本引擎中它負(fù)責(zé)定義組件配置文檔的根元素、子元素以及元素的各種屬性,使其具備良好的格式。
3) 驗(yàn)證器不是以元數(shù)據(jù)的形式呈現(xiàn)的,而是以編程的方式對(duì)配置文檔的合法性進(jìn)行驗(yàn)證,并對(duì)不合法的內(nèi)容進(jìn)行相應(yīng)的出錯(cuò)處理,其驗(yàn)證規(guī)則正是由XML Schema定義的。
4) 組件解析器的設(shè)計(jì)相對(duì)比較復(fù)雜,在整個(gè)引擎的設(shè)計(jì)中編程工作量最大。解析器首先要讀取XML文檔中某個(gè)組件的配置,然后利用反射(Reflection)API將讀取到的組件信息解析成組件對(duì)象,并依據(jù)配置中的IOC相關(guān)的信息對(duì)組件對(duì)象進(jìn)行初始化。由以上描述我們可以大概推斷出解析器的類結(jié)構(gòu),它內(nèi)部應(yīng)該維護(hù)了一個(gè)組件列表對(duì)象,同時(shí)還要提供特定的方法或函數(shù)來(lái)管理組件對(duì)象的生成,單例控制,初始化,銷毀。除此之外,它還必須向外界提供一個(gè)訪問(wèn)組件的接口,實(shí)際上,這里所說(shuō)的外界就是指圖2中的組件工廠。
3.3.2 組件工廠設(shè)計(jì)
組件工廠,即生產(chǎn)組件的場(chǎng)所,準(zhǔn)確地說(shuō),它只負(fù)責(zé)獲取組件,因?yàn)樵诒鞠到y(tǒng)中組件的生命周期是交由元數(shù)據(jù)引擎來(lái)管理的。應(yīng)用系統(tǒng)獲取組件的唯一辦法就是通過(guò)組件工廠,而不與元數(shù)據(jù)引擎直接打交道。
有了前面的元數(shù)據(jù)引擎,組件工廠的設(shè)計(jì)就相對(duì)容易多了,一種最簡(jiǎn)單的設(shè)計(jì)就是向組件的調(diào)用者暴露一個(gè)如getComponent(id)之類的方法,方法的實(shí)現(xiàn)也很容易,只需要調(diào)用元數(shù)據(jù)引擎中獲取組件的相應(yīng)方法即可。這部分的設(shè)計(jì)參照了GoF的Factory設(shè)計(jì)模式。
4 性能優(yōu)化策略及改進(jìn)建議
1) 對(duì)于采用分布式架構(gòu)的應(yīng)用系統(tǒng),由于大多數(shù)遠(yuǎn)程組件的訪問(wèn)都是通過(guò)HTTP協(xié)議完成的,所以可以考慮在客戶端、服務(wù)器,甚至在傳輸過(guò)程中所經(jīng)過(guò)的連接器上適當(dāng)施加HTTP自帶的緩存策略,可大大提高組件的訪問(wèn)性能。
2) 在本系統(tǒng)中,組件的生成以及管理是與組件的獲取分離開(kāi)的,這樣層次更加清晰。對(duì)于一些中小型的應(yīng)用,出于執(zhí)行效率考慮,可以把這兩部分合成一個(gè)單元,即把組件工廠也納入元數(shù)據(jù)引擎,與其中的解析器合并。
5 結(jié)束語(yǔ)
本文通過(guò)分析組件類型的多樣性以及EAI實(shí)施過(guò)程中的影響效率的關(guān)鍵問(wèn)題所在,提出了一套新的組件集成方案,并設(shè)計(jì)了一個(gè)與此方案相配套的輕量級(jí)IOC容器。在一定程度上優(yōu)化了組件訪問(wèn)的性能和管理策略。
參考文獻(xiàn):
[1] Masahiro Ohkawa.Provide a Facade interface for enterprise Web services [EB/OL].http://www.ibm.com/developerworks/library/ws-facade.
[2] Erich Gamma,Richard Helm,Ralph Johnson,et al.Design Patterns:Elements of Reusable Object-Oriented software[M].USA:Addison-Wesley,1995.
[3] Eric Freeman,Elisabeth Freeman,Kathy Sierra,et al.Head First Design Patterns[M].USA:O'Reilly Media,Inc,2007.
[4] 婁鋒,孫涌.輕量級(jí)IOC容器研究與設(shè)計(jì)[J].計(jì)算機(jī)技術(shù)與發(fā)展,2007,17(1):91-94.
[5] OMG.Technical Guide to Model Driven Architecture:The MDA Guide v1.0.1[EB/OL].http://www.omg.org/mda/presentations.htm.
[6] 楊中科.J2EE開(kāi)發(fā)全程實(shí)錄[M].北京:清華大學(xué)出版社,2007:102-133.
[7] 黎建輝,吳威,閻保平.一種基于XML的元數(shù)據(jù)映像與轉(zhuǎn)換方法[J].微電子學(xué)與計(jì)算機(jī),2008(1):40-44.
[8] Martin Fowler.Inversion of Control Containers and the Dependency Injection pattern[EB/OL].http://martinfowler.com/articles/injection.html.