1. 我們不禁要問竭宰,什么是"服務集群"?什么是"企業(yè)級開發(fā)"份招?
既然說了EJB 是為了"服務集群"和"企業(yè)級開發(fā)"切揭,那么,總得說說什么是所謂的"服務
集群"和"企業(yè)級開發(fā)"吧锁摔!
這個問題其實挺關鍵的廓旬,因為J2EE 中并沒有說明白,也沒有具體的指標或者事例告訴
廣大程序員什么時候用EJB 什么時候不用谐腰。于是大家都產(chǎn)生一些聯(lián)想孕豹,認為EJB"分布式運
算"指得是"負載均衡"提高系統(tǒng)的運行效率。然而十气,估計很多人都搞錯了励背,這個"服務群集"
和"分布式運算"并沒有根本解決運行負載的問題,尤其是針對數(shù)據(jù)庫的應用系統(tǒng)砸西。
為什么叶眉?
我們先把EJB 打回原形給大家來慢慢分析。
2.?把EJB 掰開了揉碎了
我們把EJB 的概念好好的分析一下芹枷,看看能發(fā)現(xiàn)些什么蛛絲馬跡衅疙。
3.1?EJB 概念的剖析
我們先看一下,EJB 的官方解釋:
商務軟件的核心部分是它的業(yè)務邏輯鸳慈。業(yè)務邏輯抽象了整個商務過程的流程饱溢,并使用計
算機語言將他們實現(xiàn)。
……
J2EE 對于這個問題的處理方法是將業(yè)務邏輯從客戶端軟件中抽取出來走芋,封裝在一個組
件中绩郎。這個組件運行在一個獨立的服務器上潘鲫,客戶端軟件通過網(wǎng)絡調(diào)用組件提供的服務以實
現(xiàn)業(yè)務邏輯,而客戶端軟件的功能單純到只負責發(fā)送調(diào)用請求和顯示處理結果肋杖。在J2EE 中溉仑,
這個運行在一個獨立的服務器上,并封裝了業(yè)務邏輯的組件就是EJB(EnterpriseJava
Bean)組件兽愤。
這其中我們主要關注這么幾點,我們來逐條剖析:
剖析1:所謂:"業(yè)務邏輯"
我們注意到在EJB 的概念中主要提到的就是"業(yè)務邏輯"的封裝挪圾,而這個業(yè)務邏輯到底是
什么浅萧?說的那么懸乎,其實這個所謂的"業(yè)務邏輯"我們完全可以理解成執(zhí)行特定任務的"類
"哲思。
剖析2:所謂:"將業(yè)務邏輯從客戶端軟件中抽取出來洼畅,封裝在組件中……運行在一個服
務器上"
既然我們知道了"業(yè)務邏輯"的概念就是執(zhí)行特定任務的"類",那么棚赔,什么叫"從客戶端
軟件中抽取出來"帝簇?其實,這個就是把原來放到客戶端的"類"靠益,拿出來不放到客戶端了,放
到一個組件中,并將這個組件放到一個服務器上去運行弦叶。
3.2 把EJB 這個概念變成大白話
變成大白話就是科盛,"把你編寫的軟件中那些需要執(zhí)行制定的任務的類,不放到客戶端軟
件上了壳快,而是給他打成包放到一個服務器上了"纸巷。
3.3 發(fā)現(xiàn)問題了
不管是用"八股文"說,還是用大白話說這個EJB 概念都提到了一個詞--"客戶端軟件"眶痰。
"客戶端軟件"瘤旨?難道EJB 的概念中說的是C/S 軟件?
是的竖伯,沒錯存哲!
EJB 就是將那些"類"放到一個服務器上,用C/S 形式的軟件客戶端對服務器上的"類"進
行調(diào)用七婴。
快崩潰了吧宏胯!
EJB 和JSP 有什么關系?EJB 和JSP 有關系本姥,但是關系還真不怎么大肩袍,至多是在JSP 的
服務器端調(diào)用遠端服務上的EJB 類,僅此而已婚惫。
4.1 EJB 的最底層究竟是什么
我們揭開了EJB"八股"概念的真諦氛赐,那么魂爪,再來分析EJB 的底層實現(xiàn)技術,通過底層實
現(xiàn)技術來分析EJB 的工作方式艰管。
4.2 EJB 的實現(xiàn)技術
EJB 是運行在獨立服務器上的組件滓侍,客戶端是通過網(wǎng)絡對EJB 對象進行調(diào)用的。在Java
中牲芋,能夠?qū)崿F(xiàn)遠程對象調(diào)用的技術是RMI撩笆,而EJB 技術基礎正是RMI。通過RMI 技術缸浦,J2EE
將EJB 組件創(chuàng)建為遠程對象夕冲,客戶端就可以通過網(wǎng)絡調(diào)用EJB 對象了。
4.3 看看RMI 是什么東東
在說RMI 之前裂逐,需要理解兩個名詞:
對象的序列化
分布式計算與RPC
名詞1:對象的序列化
對象的序列化概念:對象的序列化過程就是將對象狀態(tài)轉(zhuǎn)換成字節(jié)流和從字節(jié)流恢復對
象歹鱼。將對象狀態(tài)轉(zhuǎn)換成字節(jié)流之后,可以用java.io 包中的各種字節(jié)流類將其保存到文件中卜高,
或者通過網(wǎng)絡連接將對象數(shù)據(jù)發(fā)送到另一個主機弥姻。
上面的說法有點"八股",我們不妨再用白話解釋一下:對象的序列化就是將你程序中實
例化的某個類的對象掺涛,比如庭敦,你自定一個類MyClass,或者任何一個類的對象薪缆,將它轉(zhuǎn)換成
字節(jié)數(shù)組螺捐,也就是說可以放到一個byte 數(shù)組中,這時候矮燎,你既然已經(jīng)把一個對象放到了byte
數(shù)組中定血,那么你當然就可以隨便處置了它了,用得最多的就是把他發(fā)送到網(wǎng)絡上遠程的計算
機上了诞外。如圖:
名詞2:分布式計算與RPC
RPC 并不是一個純粹的Java 概念澜沟,因為在Java 誕生之前就已經(jīng)有了RPC 的這個概念,RPC
是"Remote Procedure Call"的縮寫峡谊,也就是"遠程過程調(diào)用"茫虽。在Java 之前的大多數(shù)編程語
言,如既们,F(xiàn)ortran濒析、C、COBOL 等等啥纸,都是過程性的語言号杏,而不是面向?qū)ο蟮摹K运拱簦@些編
程語言很自然地用過程表示工作盾致,如主经,函數(shù)或子程序,讓其在網(wǎng)絡上另一臺機器上執(zhí)行庭惜。說
白了罩驻,就是本地計算機調(diào)用遠程計算機上的一個函數(shù)。
如圖:
名詞3:二者結合就是RMI
RMI 英文全稱是"Remote Method Invocation"护赊,它的中文名稱是"遠程方法調(diào)用"惠遏,它就
是利用Java 對象序列化的機制實現(xiàn)分布式計算,實現(xiàn)遠程類對象的實例化以及調(diào)用的方法骏啰。
說的更清楚些节吮,就是利用對象序列化來實現(xiàn)遠程調(diào)用,也就是上面兩個概念的結合體器一,利用
這個方法來調(diào)用遠程的類的時候课锌,就不需要編寫Socket 程序了厨内,也不需要把對象進行序列
化操作祈秕,直接調(diào)用就行了非常方便。
遠程方法調(diào)用是一種計算機之間對象互相調(diào)用對方函數(shù)雏胃,啟動對方進程的一種機制请毛,使用這
種機制,某一臺計算機上的對象在調(diào)用另外一臺計算機上的方法時瞭亮,使用的程序語法規(guī)則和
在本地機上對象間的方法調(diào)用的語法規(guī)則一樣方仿。
如圖:
4.4 優(yōu)點
這種機制給分布計算的系統(tǒng)設計、編程都帶來了極大的方便统翩。只要按照RMI 規(guī)則設計程
序仙蚜,可以不必再過問在RMI 之下的網(wǎng)絡細節(jié)了,如:TCP 和Socket 等等厂汗。任意兩臺計算機
之間的通訊完全由RMI 負責委粉。調(diào)用遠程計算機上的對象就像本地對象一樣方便。
RMI 可將完整的對象作為參數(shù)和返回值進行傳遞娶桦,而不僅僅是預定義的數(shù)據(jù)類型贾节。也就
是說,可以將類似Java 哈西表這樣的復雜類型作為一個參數(shù)進行傳遞衷畦。
4.5 缺點
如果是較為簡單的方法調(diào)用栗涂,其執(zhí)行效率也許會比本地執(zhí)行慢很多,即使和遠程Socket
機制的簡單數(shù)據(jù)返回的應用相比祈争,也會慢一些斤程,原因是,其在網(wǎng)絡間需要傳遞的信息不僅僅
包含該函數(shù)的返回值信息菩混,還會包含該對象序列化后的字節(jié)內(nèi)容暖释。
4.6 EJB 是以RMI 為基礎的
通過RMI 技術袭厂,J2EE 將EJB 組件創(chuàng)建為遠程對象,EJB 雖然用了RMI 技術球匕,但是卻只需
要定義遠程接口而無需生成他們的實現(xiàn)類纹磺,這樣就將RMI 技術中的一些細節(jié)問題屏蔽了。
但不管怎么說亮曹,EJB 的基礎仍然是RMI橄杨,所以,如果你想了解EJB 的原理照卦,只要把RMI
的原理搞清楚就行了式矫。你也就弄清楚了什么時候用EJB 什么時候不需要用EJB 了。
5.?EJB 中所謂的"服務群集"
既然已經(jīng)知道了役耕,RMI 是將各種任務與功能的類放到不同的服務器上采转,然后通過各個服
務器間建立的調(diào)用規(guī)則實現(xiàn)分布式的運算,也就明白EJB 所謂的"服務群集"的概念瞬痘。
就是將原來在一個計算機上運算的幾個類故慈,分別放到其他計算機上去運行,以便分擔運
行這幾個類所需要占用的CPU 和內(nèi)存資源框全。同時察绷,也可以將不同的軟件功能模塊放到不同的
服務器上,當需要修改某些功能的時候直接修改這些服務器上的類就行了津辩,修改以后所有客
戶端的軟件都被修改了拆撼。如圖:
6.?這種部署難道是無懈可擊
上圖所示的這個"服務群集"看似"無懈可擊",其實是它這個圖沒有畫完整喘沿,我們來
把這個圖畫完整闸度,再來看看有什么問題沒有。
6.1 瓶頸在數(shù)據(jù)庫端
仔細觀察之后蚜印,發(fā)現(xiàn)這種配置是有瓶頸的莺禁,如圖:
我們看看上圖的結構圖,現(xiàn)在如果想實現(xiàn)各個服務器針對同一個數(shù)據(jù)庫的查詢晒哄,那
么睁宰,不管你部署多少個功能服務器,都需要針對一個數(shù)據(jù)庫服務器進行查詢操作寝凌。也就是說柒傻,
不管你的"計算"有多么"分布"也同樣需要從一臺服務器中取得數(shù)據(jù)。雖然较木,看起來將各個功
能模塊分布在不同的服務器上從而分擔了各個主計算機的CPU 資源红符,然而,真正的瓶頸并不
在這里,而是预侯,數(shù)據(jù)庫服務器那里致开。數(shù)據(jù)庫服務器都會非常忙的應付各個服務器的查詢及操
作請求。
因此萎馅,通過這個結構圖使我們了解到了EJB 根本不能完全解決負載的問題双戳,因為,瓶頸
并不在功能模塊的所在位置糜芳,而是在數(shù)據(jù)庫服務器這里飒货。
6.2 假如分開數(shù)據(jù)庫,數(shù)據(jù)共享怎么辦
有的讀者一定會想到下面的這個應用結構峭竣,如圖:
就是把每一個功能服務器后面都部署一個數(shù)據(jù)庫塘辅,這樣不就解決了上節(jié)所說的問題了
嗎?是的解決了數(shù)據(jù)庫查詢負載的問題皆撩,然而又出現(xiàn)了新的問題扣墩,就是"數(shù)據(jù)共享"的問題就
又不容易解決了。
6.3 網(wǎng)絡面臨較大壓力扛吞,讓你的應用慢如老牛
我們再向前翻看看如上圖所示的這種架構中存在兩個網(wǎng)絡呻惕,一個是"A 網(wǎng)"一個是"B
網(wǎng)",這兩個網(wǎng)絡是不同的喻粹。"B 網(wǎng)"往往是局域網(wǎng)蟆融,一般帶寬是10M/100M草巡,速度較快守呜,因此
到還好說,然而山憨,"A 網(wǎng)"往往是互聯(lián)網(wǎng)或者是利用電信網(wǎng)絡互聯(lián)VPN 網(wǎng)或稱廣域網(wǎng)查乒。"A 網(wǎng)"
的特點是帶寬一般較窄,如ADSL 的網(wǎng)絡僅僅有512K-2M 的帶寬郁竟,由于廣域網(wǎng)互聯(lián)的成本較
高玛迄,所以一般不會有較高的帶寬。
而在這個網(wǎng)絡上恰恰跑的是功能模塊和客戶端軟件之間交換的數(shù)據(jù)棚亩,而這部分數(shù)據(jù)恰恰
優(yōu)勢非常占用帶寬的蓖议。
因此,這個應用架構其運行速度可以想見是多么的慢了讥蟆。說句不夸張的話勒虾,有點想老牛
拉破車一樣的慢。
一個如老牛的系統(tǒng):
目前在中國互聯(lián)網(wǎng)做運營商網(wǎng)絡管理系統(tǒng)的一個大公司瘸彤,它的一個早期的網(wǎng)管軟件就是
采用了這種架構來做的C/S 結構的應用系統(tǒng)修然。
有一次,我作為評估者來對其應用系統(tǒng)進行評估,將其部署到一個非運營商大型的網(wǎng)絡
中的時候愕宋,便出現(xiàn)了我們上述描述的情況玻靡,速度已經(jīng)到了難以忍受的地步,打開一個流量圖中贝,
有時候需要用15分鐘的時間才能呈現(xiàn)完整囤捻。然而,該系統(tǒng)在開發(fā)階段并沒有發(fā)現(xiàn)這個問題邻寿,
為什么呢最蕾?因為,他們沒有考慮到應用的實際用戶連接網(wǎng)絡的復雜性老厌,從而給該公司造成較
大損失瘟则,以至于,這個開發(fā)架構被最終遺棄枝秤。
7.?EJB 活學活用醋拧,J2EE 不是必須使用EJB
通過上面小節(jié)的講解似乎好像EJB 和開發(fā)Web 應用的B/S 結構的系統(tǒng)關系并不大,其實
倒也不然淀弹。我們?nèi)绻?客戶端程序"理解成某一臺服務器丹壕,這樣也是可以被應用的,而且薇溃,
如果是服務器互相之間做EJB 的調(diào)用的話菌赖,也就不存在廣域網(wǎng)帶寬限制的問題了。
但是沐序,如下情況盡量就不要使用EJB 了:
1琉用、較為簡單的純Web 應用開發(fā),不需要用EJB策幼。
2邑时、需要與其他服務程序配合使用的應用,但調(diào)用或返回的自定義的網(wǎng)絡協(xié)議可以解決
的應用程序,不需要使用EJB特姐。
3晶丘、較多人并發(fā)訪問的C/S 結構的應用程序,盡量不要使用EJB唐含。
總結:
a.EJB實現(xiàn)原理:就是把原來放到客戶端實現(xiàn)的代碼放到服務器端浅浮,并依靠RMI進行通信。
b.RMI實現(xiàn)原理:就是通過Java對象可序列化機制實現(xiàn)分布計算捷枯。
c.服務器集群:就是通過RMI的通信滚秩,連接不同功能模塊的服務器,以實現(xiàn)一個完整的功能铜靶。