JBoss的集群策略分析(來源:http://www.yesky.com) 序言 在閱讀本文前,,請(qǐng)確定您有以下基礎(chǔ),,否則您可能會(huì)是在浪費(fèi)您的時(shí)間: 1、 了解J2EE的一些基本概念 2,、 了解集群的基本概念 3,、 對(duì)JBOSS有一些大致的了解,可到http://www.上下載它,。 JBOSS是一個(gè)開放源碼的,、基于J2EE規(guī)范的應(yīng)用服務(wù)器,它實(shí)現(xiàn)了大多數(shù)的J2EE規(guī)范,,除此之外,,它還提供了一些J2EE中所沒有涉及到的企業(yè)級(jí)功能,例如集群,。本文主要描述JBOSS采取的集群策略,,并重點(diǎn)介紹它的負(fù)載平衡與失效轉(zhuǎn)發(fā)機(jī)制。 由于JBOSS是一個(gè)建立在J2EE規(guī)范上的應(yīng)用服務(wù)器,,因此在開始之前,,我們還是簡(jiǎn)單地介紹一下J2EE規(guī)范:J2EE是一套針對(duì)于企業(yè)級(jí)分布式應(yīng)用的計(jì)算環(huán)境,它定義了動(dòng)態(tài)WEB頁(yè)面功能(servlet和jsp),商業(yè)組件(EJB),,異步消息傳輸機(jī)制(JMS),,名稱和目錄定位服務(wù)(JNDI),數(shù)據(jù)庫(kù)訪問(JDBC),與子系統(tǒng)的連接器(JCA),,安全服務(wù)等等,。 但美中不足的是J2EE并沒有定義一些企業(yè)級(jí)應(yīng)用所必須的規(guī)范,例如集群,,所以集群的實(shí)現(xiàn)只能由各廠商自行來設(shè)計(jì)實(shí)現(xiàn),。要實(shí)現(xiàn)基于J2EE規(guī)范的集群,我們通常要做如下考慮:集群的管理,、負(fù)載平衡,、失效轉(zhuǎn)發(fā)、服務(wù)端狀態(tài)的復(fù)制(例如JSP中的session),,還要考慮同步和異步的問題(例如JMS服務(wù)就是異步方式),。如果要對(duì)這些內(nèi)容做一個(gè)全面的闡述的話,估計(jì)可以寫成一本書了:) 因此本文主要探討的是:怎樣實(shí)現(xiàn)無(wú)狀態(tài)EJB的負(fù)載平衡與失效轉(zhuǎn)發(fā)機(jī)制,? 1999年,,Marc Fleury建立了JBOSS開源項(xiàng)目,現(xiàn)在它有差不多100個(gè)活躍的開發(fā)者,,30個(gè)核心開發(fā)者,,每月高達(dá)35萬(wàn)次的下載量,它當(dāng)前的最高穩(wěn)定版是3.2版,,4.0版正在穩(wěn)定之中,,自從JBOSS3.0開始就加入了集群技術(shù),幾乎能對(duì)任何J2EE規(guī)范進(jìn)行集群管理,,如JNDI,、JSP中的session、EJB等等,。更令人振奮的是,,即將發(fā)行的JBOSS4.0將會(huì)對(duì)JMS也加入集群管理特色。
EJB集群在JBOSS中的實(shí)現(xiàn) 下面言歸正傳,,上圖大致描述了一個(gè)客戶端調(diào)用JBOSS中的EJB的過程。在JBOSS中,,客戶端并不直接調(diào)用EJB對(duì)像,,而采用了一個(gè)迂回的方法,更專業(yè)的說是一種設(shè)計(jì)模式――代理模式,,真正與客戶端交互的是一個(gè)代理對(duì)像①,,這個(gè)代理對(duì)像一般由客戶端通過JNDI技術(shù)來取得的。而具體的代理對(duì)像的實(shí)現(xiàn)就由各廠商自完成了,,在JBOSS中,,一個(gè)代理對(duì)像是一段精心設(shè)計(jì)的復(fù)雜代碼。 但在客戶端看來,調(diào)用一個(gè)代理對(duì)像好像就是在調(diào)用那個(gè)實(shí)際的EJB對(duì)像,,雖然事實(shí)并非如此,。在這里JBOSS耍了一個(gè)小把戲,代理對(duì)像雖然實(shí)現(xiàn)了與EJB對(duì)像相同的接口,,但它實(shí)際上是把客戶端對(duì)它的調(diào)用轉(zhuǎn)發(fā)到了它在服務(wù)端的另一個(gè)伙伴身上②,,同時(shí),這個(gè)伙伴同樣定義了客戶端所要求的一些EJB接口,,當(dāng)這些接口被調(diào)用時(shí)③,,精彩的部分開始了,JBOSS把客戶端發(fā)過來的各種各樣不同的調(diào)用全部轉(zhuǎn)換成為一個(gè)統(tǒng)一格式的接口④(在本文中我們暫且稱客戶端發(fā)出的調(diào)用為應(yīng)用級(jí)接口,,而JBOSS生成的統(tǒng)一格式的接口稱為系統(tǒng)級(jí)接口),。當(dāng)轉(zhuǎn)換完成后,所有的應(yīng)用級(jí)接口變成了系統(tǒng)級(jí)接口⑤,。為了能更清楚地闡述這個(gè)問題,,我們假設(shè)客戶端向EJB對(duì)像發(fā)出如下調(diào)用:
這個(gè)調(diào)用實(shí)際上被JBOSS轉(zhuǎn)換成了如下的系統(tǒng)級(jí)調(diào)用:
但這個(gè)invocation到底是什么呢?實(shí)際上它是類Invocation的一個(gè)實(shí)例,,這里有它的一個(gè)簡(jiǎn)單的說明:
當(dāng)應(yīng)用級(jí)接口被轉(zhuǎn)換成為了系統(tǒng)級(jí)接口之后,,它將經(jīng)過一系列的攔截器(⑥至⑦)。在這里我首先要說明一下什么是攔截器,,實(shí)際上,,它是JBOSS中獨(dú)具特色的一個(gè)設(shè)計(jì)思路,一個(gè)攔截器就好像是一張過濾網(wǎng),,它用來對(duì)客戶端的調(diào)用進(jìn)行攔截,,并對(duì)其進(jìn)行一些處理,比如檢查客戶端調(diào)用的合法性,、實(shí)現(xiàn)安全策略,、對(duì)事務(wù)進(jìn)行支持等。值得一提的是,,JBOSS的集群管理也是通過攔截器來實(shí)現(xiàn)的,,更令人欣慰的是,JBOSS的設(shè)計(jì)者并沒有將這個(gè)攔截器固化在其核心內(nèi),,而是采用一種插件式(plug-in)的方法來設(shè)計(jì),,因此你只要實(shí)現(xiàn)它的插件接口,你甚至可以寫出自己的攔截器來,,當(dāng)然,,這已不屬于本文的討論范圍之內(nèi)了。 值得注意的是最后一個(gè)攔截器,,它有一些特殊,因?yàn)樗耪嬲貓?zhí)行對(duì)實(shí)際的EJB的調(diào)用⑧,,它能檢測(cè)到客戶端是否和EJB對(duì)像在同一個(gè)Java虛擬機(jī)中,,如果是的話,它只是簡(jiǎn)單地將這個(gè)調(diào)用直接傳給EJB對(duì)像,,這樣做的原因是可以避免由于網(wǎng)絡(luò)傳輸帶來的不必要的開銷,,使用調(diào)用速度大大加快。 上圖中的3種方案都有其利弊,,但我們覺得最后一個(gè)方法要比前2個(gè)好,,原因如下: 因此,,我們選擇了最后一種方案來做為JBOSS的集群策略。其實(shí),,只要大家再仔細(xì)回顧一下前面的部分,,就會(huì)發(fā)現(xiàn)我們先前描述的方案不正是第3種方案嗎?但我們現(xiàn)在必須對(duì)這個(gè)策略在以下幾個(gè)方面做一些更深入的分析: 負(fù)載平衡的設(shè)計(jì)策略 前面已經(jīng)說過,JBOSS的負(fù)載平衡與失效轉(zhuǎn)發(fā)策略是由最后一個(gè)攔截器實(shí)現(xiàn)的(上圖中的①),,然而我們要考慮的是雖然客戶端只發(fā)出一個(gè)調(diào)用,,但針對(duì)于代理對(duì)像的調(diào)用可能包含多個(gè)可用的服務(wù)器結(jié)點(diǎn),其個(gè)數(shù)等于集群中所有有效節(jié)點(diǎn)之和(參見上圖中的②),,那么到底是由誰(shuí)來決定這個(gè)策略的呢,?這個(gè)工作由一個(gè)叫插件式的負(fù)載平衡策略來實(shí)施的(在下一段中簡(jiǎn)稱策略①,如下圖)。 當(dāng)客戶端調(diào)用到達(dá)最后一個(gè)攔截器的時(shí)候,,攔截器會(huì)請(qǐng)求策略①來為它選擇一個(gè)服務(wù)器結(jié)點(diǎn),。如果此結(jié)點(diǎn)有效且調(diào)用成功,則結(jié)果會(huì)返回給代理對(duì)像,,如果失敗了,,攔截器不會(huì)直接將錯(cuò)誤返回給代理對(duì)像,,而是將這個(gè)錯(cuò)誤信息報(bào)告給策略①,并請(qǐng)求它再為客戶端選擇一個(gè)新節(jié)點(diǎn),。 但還有一個(gè)問題值得考慮的,,就是對(duì)一些致命性錯(cuò)誤的處理。例如某個(gè)數(shù)據(jù)庫(kù)服務(wù)器突然崩潰了,,那么最后一個(gè)攔截器將無(wú)法對(duì)此進(jìn)行失效轉(zhuǎn)發(fā)了,,因?yàn)椴还苓x擇哪個(gè)服務(wù)器結(jié)點(diǎn)都不能解決這個(gè)問題了,在這里攔截器會(huì)將錯(cuò)誤報(bào)告給客戶端,,并由其自已做出決定,。 IT界里好像有這樣一個(gè)原理,就是"越是可擴(kuò)展性強(qiáng),,靈活的東西實(shí)施起來就越復(fù)雜",。在JBOSS中也不例外,但幸運(yùn)的是這些工作并沒為給客戶端帶來額外的編程負(fù)擔(dān),,因?yàn)樗胁呗缘呐渲枚际窃诜?wù)器完成的,。 JBOSS的集群配置遵循XML規(guī)范,下面是的一個(gè)普通EJB對(duì)像的典型集群配置:
上述配置說明了一個(gè)名為MySessionBean的會(huì)話Bean的集群策略,,它定義了名為DefaultPartion的缺省策略名稱,并定義了2個(gè)具體的策略,。當(dāng)然,,如果你覺得它比較復(fù)雜,而只想用JBOSS缺省的集群策略的話,,可以將整個(gè)<cluster-config>標(biāo)簽去掉,。 服務(wù)器結(jié)點(diǎn)拓?fù)鋱D的刷新 JBOSS的集群實(shí)現(xiàn)是動(dòng)態(tài)的,,也就是說你可以動(dòng)態(tài)地往集群中加入一個(gè)新節(jié)點(diǎn)或關(guān)閉任意一個(gè)節(jié)點(diǎn),而不用費(fèi)力地維護(hù)一張靜態(tài)的拓?fù)鋱D,,就好像是JBOSS自己有能力管理集群一樣,。這個(gè)思想夠先進(jìn)吧?但與此同時(shí)它也帶來了一些令人頭痛的問題,,請(qǐng)先看下圖: 由于JBOSS的集群策略是在客戶端進(jìn)行的,,那么客戶端在調(diào)用EJB的時(shí)候會(huì)將所有必須的組件下載下來,然后由其進(jìn)行集群決策,。如果我們?cè)O(shè)T為時(shí)間,,且t0<t1<t2,那么當(dāng)處于t0時(shí)刻時(shí),,集群拓?fù)鋱D中包含server1和server2兩個(gè)節(jié)點(diǎn),,客戶端的調(diào)用被轉(zhuǎn)發(fā)到了結(jié)點(diǎn)2上。當(dāng)處于t1時(shí)刻時(shí),,server1和server2全部都崩潰了,。當(dāng)處于t2時(shí)刻時(shí),管理員增加了server3和server4兩個(gè)節(jié)點(diǎn),,但客戶端的拓?fù)鋱D中還只是包含原先的server1和server2兩節(jié)點(diǎn)的信息,,因?yàn)樗鼰o(wú)法知道這新加入的2個(gè)節(jié)點(diǎn)。 為了解決這個(gè)問題,,JBOSS是這樣設(shè)計(jì)的,,在客戶端的每次對(duì)某個(gè)節(jié)點(diǎn)調(diào)用后,服務(wù)器節(jié)點(diǎn)自動(dòng)檢查客戶的拓?fù)鋱D是不是最新的,,如果不是,,則向客戶端發(fā)送新的拓?fù)鋱D,如下圖所示: 當(dāng)客戶端進(jìn)行調(diào)用時(shí),,代理對(duì)像對(duì)其進(jìn)行了一個(gè)小小的包裝,,它將系統(tǒng)級(jí)調(diào)用invocation和自已現(xiàn)在的拓?fù)鋱D(JBOSS開發(fā)者稱它為view ID)發(fā)送到服務(wù)端,而服務(wù)端則檢查它自己的view ID是否與代理對(duì)像中的view ID吻合,。這里我們先簡(jiǎn)單介紹一下view ID,,它實(shí)際上就是包含所有服務(wù)器節(jié)點(diǎn)的一個(gè)哈希表,,至于為什么要用哈希表是因?yàn)樗煞奖悖╦ava編譯器自帶)、存取快速,,無(wú)須考慮排序問題,。 下面接著講述,如果代理對(duì)像的view ID與服務(wù)端節(jié)點(diǎn)的view ID相吻合的話,,服務(wù)端將直接把結(jié)果傳給EJB對(duì)像,,并將結(jié)果返回。 如果服務(wù)器集群拓?fù)洚a(chǎn)生了變化,,則會(huì)導(dǎo)致它們不吻合,。這時(shí)服務(wù)器節(jié)點(diǎn)同樣也將調(diào)用EJB對(duì)像,但此時(shí)返回的結(jié)果有所不同,,它除了返回客戶端的結(jié)果外,,還要為代理對(duì)像返回一個(gè)最新的view ID,并通知代理對(duì)像:"喂,,你的拓?fù)鋱D太舊了,,我發(fā)了份新的,你趕快更新一下吧,!" 當(dāng)代理對(duì)像收到這個(gè)消息后會(huì)更新自己的view ID,,并將結(jié)果返回客戶端代碼。
性能考慮 結(jié)論 |
|