作者: Anders小明
什麼是公司專屬應用程式下的業務組件
首先,這是一個組件,這意味著它需要在容器裡運行,因此不包括任何中介軟體服務,同時以一定結構(檔案結構或者壓縮格式)組成,被容器識別;其次,這是一個業務組件,即提供的是應用服務,而非技術服務;第三,這是公司專屬應用程式,在業務上包括功能和服務(Service,當前最時髦的說法,你可以理解為API),技術上(以J2EE來講)包括:UI資源(JSF、JSP、JS和CSS等)、應用程式(Java)資源和設定檔、資料庫表定義、初始化資料和預存程序。
為什麼要公司專屬應用程式下的業務組件
組件技術從提出到現在已經有20多年了,為什麼要提公司專屬應用程式業務組件?因為現有的組件技術不支援公司專屬應用程式環境下的組件要求,J2EE的EJB不支援,.NET的DLL也不支援。
如前所述,一個公司專屬應用程式通常包括了互動介面、應用代碼以及資料庫結構,而不論是EJB還是DLL只支援應用代碼,都不包括互動介面和資料庫結構。
如果說EJB不是,那麼J2EE的EAR或者WAR是否算是一個組件?答案也不是,EAR或者WAR部署的是一個公司專屬應用程式,請注意EJB規範中明確說:The Enterprise JavaBeans architecture is a architecture for the development and deployment of component-based (distributed) business applications(EJB 2.x和3.x唯一的區別是2.x有distributed),它們有自己的應用域,彼此相互隔離(簡單的看,它們有各自獨立的會話管理)。.NET也是有自己的應用域概念。
更進一步,基於應用的部署導致了三個隔離問題:互動(介面)隔離、程式訪問隔離和資料隔離(請注意這三個問題分別對應了公司專屬應用程式業務組件的三個技術內容)。互動隔離導致了企業使用者必須訪問不同介面,代碼訪問隔離導致了點對點的整合以及諸如效能、事務和非同步處理等各種非功能性問題,而資料隔離導致了資料有效性、一致性等等問題。所有這些都進而導致了維護的問題。
為瞭解決這些問題,大廠商們都提出了各種解決方案:Portal來解決互動隔離問題,通過ESB來解決代碼訪問隔離問題,以及通過所謂的資訊服務(Information Service)來解決資料隔離問題。
那麼OSGi技術或者SCA技術能否滿足要求?答案是目前不能,OSGi最初開發的目的就不是為了公司專屬應用程式,只是這幾年開始成熟,並向公司專屬應用程式方向發展。09年推出的企業版(草案)剛剛提出針對程式訪問問題的方案,如遠程服務、交易管理等;互動隔離問題上規範並沒有提出相應方案,只有Eclipse的Equinox提出了介面的擴充點機制,但這也不能解決B/S環境的問題;而資料隔離問題就沒有任何方案。SCA從一開始就是面向公司專屬應用程式,不過不解決互動隔離和資料隔離問題。
此外,對於行業ISV來說,除企業使用者面臨的這些種種問題,還面臨著其它問題。企業使用者畢竟只是面對自己的需求,行業ISV卻面臨著多個企業使用者的需求,面臨定製化帶來的維護問題,特別是業務和技術的隔離問題(即如何保持構建業務組件的所使用技術的平穩升級)。
組件的容器
既然要公司專屬應用程式下的業務組件,而現有的組件技術又無法支撐,那麼就需要一個新的組件容器了(當然,作為一個普通開發人員,我們無法建立一個公開標準的組件體系,也獨立維護一個私人的)。新的組件容器完全使用現有的中介軟體技術,並加上一些新的內容,包括如下:
- 組件架構,識別組件,以及組件(檔案)結構和各個技術工件。
- 技術架構,提供業務無關的支援人員,以便於技術的平穩升級切換。
- 運行容器,採用現有中介軟體技術,包括Tomcat、應用伺服器和資料庫服務等;
- 工具,包括打包以及部署工具等。
關於資料隔離問題,在EIP中提到了各種解決方案,這裡採用的共用資料庫方式,即各個組件都共用一個資料庫,各個組件只提供資料庫定義和初時資料(如同EJB/OSGi一樣,運行時環境由容器提供)。
組件的關係
組件的關係分為兩種:依賴和聯動。依賴關係在已有的組件技術上已經廣為認知,而聯動則是新創造的(肯定不是第一個建立的,只不過不同人有不同的叫法)。
聯動和依賴的區別是:如果有組件B和組件A聯動,則組件B可以在沒有組件A的情況下運行,並提供相應功能。
針對三種不同技術工件(即三個隔離問題)呈現不同特點,如下:
1. UI資源(互動隔離問題),依賴是指UI資源的嵌入、引用和替換,聯動是指UI資源的新增。
2. 應用程式(程式訪問隔離),依賴是指API/模型依賴,聯動是指訊息(傳統訊息和JMS訊息)以及SPI實現。其中,無論是依賴或者聯動都涉及到相應的非功能性需求,包括:非同步、事務控制和服務時限等。
3. 資料庫資源(資料隔離),依賴是指外部索引鍵關聯和級聯操作,無明顯的聯動關係。
這裡,需要關注應用程式的依賴和聯動
1. SPI和API存在業務不匹配問題。
雖然組件A相依元件B,但是不代表組件B提供的服務完全符合組件A的要求。有時組件A所需要的資料需要組件B的多個API組成,為了開發方便或者組件A所需要的效能問題,可能會在組件B新寫一個介面給組件A使用,注意該介面不是組件B的API,該介面僅適用於組件A。
2. 儘可能的使用SPI整合方式
SPI整合方式是相對於API整合方式,API整合方式就是,組件B直接調用其它組件的API及其模型。SPI整合方式(類似於依賴倒置),組件B定義其所需要的介面及其模型,由組件A或者膠水層代碼來實現。
這個點對於行業ISV尤為明顯。對於企業使用者來說,依賴是明確的,組件A依賴/聯動於組件B,但對於行業ISV,則面臨著定製化問題,雖然組件A依賴/聯動於組件B,但是在某個定製化項目中,由於客戶已有系統C,而需要組件A依賴/聯動於客戶已有系統C。此時採用SPI方式。
在開源世界裡採用SPI方式更是廣泛。很多架構為了相容(同一功能)不同實現的類庫,都是先定義架構所需介面,並同時提供不同類庫的膠水代碼。
不論是EJB/OSGi/SCA都沒有對SPI整合方式的支援。
3. 依賴和聯動的非功能性需求。
事實上,非功能性需求都是在整合時才存在的。以交易管理為例,除了及其少數的例子外,大部分事務只能在處理流程才被決定(注意,EJB在這方面著是定義在API上的,這樣的設計是不適應需求的),而組件A的API在用例1中需要被非同步呼叫,而在用例2中需要被同步調用是常見的。即便是OSGi規範,也在這方面沒有任何處理。
組件的定製化
定製化問題只針對於行業ISV有效,對於企業使用者來說,除非是那種跨國企業在面臨不同國度的業務模式、法律監管和會計制度等差異,存在定製化需要,即使如此,ISV和企業使用者對於同一問題的解決方式也是不同的。
既然我們已經將原有的應用採用組件化方式開發,那麼應用的定製化問題就轉化為組件的定製化問題。同樣,應用的定製化手段也就轉化為組件的定製化手段。
組件架構
羅羅嗦嗦的說了半天,有人就說了:這不就是把UI、Java和資料庫三個東東一打包,然後說這就是一個公司專屬應用程式下的業務組件,有啥新意呢,不就是模組化開發嘛,一直一來大家都是就是這麼搞的嘛,何必搞個怪名詞來忽悠。
是的,就是把UI、Java和資料庫三個東東整合在一起,組件容器說提到的技術架構很多的開發隊伍都有一套,運行容器更是有無數開源商業的,打包部署工具更是寫了無數。
這確確實實就是我們常說的模組化開發。但是模組化開發不同於組件開發,模組化開發只是在邏輯上做了切分,物理上(開發出的系統代碼)通常並沒有真正意義上的隔離,一切都只是在文檔中。
我們需要一點乾貨,只有實實在在的組件架構才能組件化開發真正落地的(如同OSGi架構那樣):我們需要一個類似於Equinox的介面擴充架構來支援UI資源的依賴和聯動;我們需要一個整合架構來支援應用程式的依賴和聯動,解決所面臨的種種問題(業務不匹配、SPI整合以及各種非功能性需求);我們需要一個打包部署工具(類似Spring DM)提供部署UI資源、應用程式和資料庫定義資源(Spring DM提供了基於Web資源的部署能力)。
其它問題
對於採用J2EE下B/S環境的組件應用還面臨一個問題,即現有Servlet規範只允許一個web.xml,不支援組件各自訂私人的Filter和Servlet,不過這個問題不是很嚴重,在現有技術架構已經支援一份簡單的web.xml,而新的Servlet規範已經允許多個web.xml。
分布式部署以及叢集部署問題,這其實不是個問題。基於應用的我們有很多手段和技術,那麼基於組件的也一樣有辦法。