午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

JBoss的集群策略分析

 david.tao 2006-07-13

JBoss的集群策略分析


(來源:http://www.yesky.com)

序言

  在閱讀本文前,請確定您有以下基礎(chǔ),否則您可能會是在浪費您的時間:

  1、 了解J2EE的一些基本概念

  2、 了解集群的基本概念

  3、 對JBOSS有一些大致的了解,可到http://www.上下載它。 JBOSS是一個開放源碼的、基于J2EE規(guī)范的應(yīng)用服務(wù)器,它實現(xiàn)了大多數(shù)的J2EE規(guī)范,除此之外,它還提供了一些J2EE中所沒有涉及到的企業(yè)級功能,例如集群。本文主要描述JBOSS采取的集群策略,并重點介紹它的負載平衡與失效轉(zhuǎn)發(fā)機制。

  由于JBOSS是一個建立在J2EE規(guī)范上的應(yīng)用服務(wù)器,因此在開始之前,我們還是簡單地介紹一下J2EE規(guī)范:J2EE是一套針對于企業(yè)級分布式應(yīng)用的計算環(huán)境,它定義了動態(tài)WEB頁面功能(servlet和jsp),商業(yè)組件(EJB),異步消息傳輸機制(JMS),名稱和目錄定位服務(wù)(JNDI),數(shù)據(jù)庫訪問(JDBC),與子系統(tǒng)的連接器(JCA),安全服務(wù)等等。

  但美中不足的是J2EE并沒有定義一些企業(yè)級應(yīng)用所必須的規(guī)范,例如集群,所以集群的實現(xiàn)只能由各廠商自行來設(shè)計實現(xiàn)。要實現(xiàn)基于J2EE規(guī)范的集群,我們通常要做如下考慮:集群的管理、負載平衡、失效轉(zhuǎn)發(fā)、服務(wù)端狀態(tài)的復(fù)制(例如JSP中的session),還要考慮同步和異步的問題(例如JMS服務(wù)就是異步方式)。如果要對這些內(nèi)容做一個全面的闡述的話,估計可以寫成一本書了:) 因此本文主要探討的是:怎樣實現(xiàn)無狀態(tài)EJB的負載平衡與失效轉(zhuǎn)發(fā)機制?

  1999年,Marc Fleury建立了JBOSS開源項目,現(xiàn)在它有差不多100個活躍的開發(fā)者,30個核心開發(fā)者,每月高達35萬次的下載量,它當前的最高穩(wěn)定版是3.2版,4.0版正在穩(wěn)定之中,自從JBOSS3.0開始就加入了集群技術(shù),幾乎能對任何J2EE規(guī)范進行集群管理,如JNDI、JSP中的session、EJB等等。更令人振奮的是,即將發(fā)行的JBOSS4.0將會對JMS也加入集群管理特色。

 




  EJB集群在JBOSS中的實現(xiàn)

  下面言歸正傳,上圖大致描述了一個客戶端調(diào)用JBOSS中的EJB的過程。在JBOSS中,客戶端并不直接調(diào)用EJB對像,而采用了一個迂回的方法,更專業(yè)的說是一種設(shè)計模式――代理模式,真正與客戶端交互的是一個代理對像①,這個代理對像一般由客戶端通過JNDI技術(shù)來取得的。而具體的代理對像的實現(xiàn)就由各廠商自完成了,在JBOSS中,一個代理對像是一段精心設(shè)計的復(fù)雜代碼。

  但在客戶端看來,調(diào)用一個代理對像好像就是在調(diào)用那個實際的EJB對像,雖然事實并非如此。在這里JBOSS耍了一個小把戲,代理對像雖然實現(xiàn)了與EJB對像相同的接口,但它實際上是把客戶端對它的調(diào)用轉(zhuǎn)發(fā)到了它在服務(wù)端的另一個伙伴身上②,同時,這個伙伴同樣定義了客戶端所要求的一些EJB接口,當這些接口被調(diào)用時③,精彩的部分開始了,JBOSS把客戶端發(fā)過來的各種各樣不同的調(diào)用全部轉(zhuǎn)換成為一個統(tǒng)一格式的接口④(在本文中我們暫且稱客戶端發(fā)出的調(diào)用為應(yīng)用級接口,而JBOSS生成的統(tǒng)一格式的接口稱為系統(tǒng)級接口)。當轉(zhuǎn)換完成后,所有的應(yīng)用級接口變成了系統(tǒng)級接口⑤。為了能更清楚地闡述這個問題,我們假設(shè)客戶端向EJB對像發(fā)出如下調(diào)用:

 

myRemoteComponent.increaseSalary(100); 
//myRemoteComponent為代理對像

  這個調(diào)用實際上被JBOSS轉(zhuǎn)換成了如下的系統(tǒng)級調(diào)用:

proxyClientContainer.invoke(invocation);
//proxyClientContainer為代理對像在服務(wù)端的另一個伙伴

  但這個invocation到底是什么呢?實際上它是類Invocation的一個實例,這里有它的一個簡單的說明:

public class Invocation{
 Object[] args; //應(yīng)用級接口中的一些參數(shù)
 Method method; //被調(diào)用的應(yīng)用級接口
 Map payload; //JBOSS就是在這里采取的負載平衡策略的
 ……
}

  當應(yīng)用級接口被轉(zhuǎn)換成為了系統(tǒng)級接口之后,它將經(jīng)過一系列的攔截器(⑥至⑦)。在這里我首先要說明一下什么是攔截器,實際上,它是JBOSS中獨具特色的一個設(shè)計思路,一個攔截器就好像是一張過濾網(wǎng),它用來對客戶端的調(diào)用進行攔截,并對其進行一些處理,比如檢查客戶端調(diào)用的合法性、實現(xiàn)安全策略、對事務(wù)進行支持等。值得一提的是,JBOSS的集群管理也是通過攔截器來實現(xiàn)的,更令人欣慰的是,JBOSS的設(shè)計者并沒有將這個攔截器固化在其核心內(nèi),而是采用一種插件式(plug-in)的方法來設(shè)計,因此你只要實現(xiàn)它的插件接口,你甚至可以寫出自己的攔截器來,當然,這已不屬于本文的討論范圍之內(nèi)了。

  這里(⑥至⑦)的每個攔載器將順序地攔截invocation,它們都具有如下的集群管理方面的能力:

  1、 分析invocation的內(nèi)容和任務(wù)。

  2、 加入一些信息到invocation中的payload中,以優(yōu)化集群策略。

  3、 讀取出放在payload中的任何可用信息。

  4、 將invocation轉(zhuǎn)發(fā)到下一個攔截器中。

  5、 如果發(fā)生錯誤,能夠?qū)㈠e誤報告給調(diào)用者,并返回到正確的地方去。

  值得注意的是最后一個攔截器,它有一些特殊,因為它才真正地執(zhí)行對實際的EJB的調(diào)用⑧,它能檢測到客戶端是否和EJB對像在同一個Java虛擬機中,如果是的話,它只是簡單地將這個調(diào)用直接傳給EJB對像,這樣做的原因是可以避免由于網(wǎng)絡(luò)傳輸帶來的不必要的開銷,使用調(diào)用速度大大加快。

  另一方面,如果客戶端與EJB不在同一個虛擬機中,那么它們就要通過網(wǎng)絡(luò)傳輸了,在這里JBOSS提供了另一個有趣的策略,就是代理對像并不知道采取的是什么傳輸協(xié)議,只有最后那個攔截器才知道真正采用的傳輸協(xié)議是什么。就目前而言,它提供了RMI/JRMP、IIOP、HTTP、SOAP等協(xié)議來進行傳輸。
當我們設(shè)計JBOSS的集群策略時,我們還必須決定究竟要在哪兒將負載平衡以及失效轉(zhuǎn)發(fā)行激活,為此,請先看下圖:



  1、 在某個服務(wù)器結(jié)點上發(fā)生

  2、 在一個中介服務(wù)器上進行發(fā)生

  3、 在客戶端上進行發(fā)生

  上圖中的3種方案都有其利弊,但我們覺得最后一個方法要比前2個好,原因如下:

  1、 與第2種方案相比,它避免了由于中介服務(wù)器失效而引發(fā)的全線崩潰。

  2、 除非客戶端崩潰,負載平衡和失效轉(zhuǎn)發(fā)策略才會失敗。而我想應(yīng)該沒有人會對此產(chǎn)生報怨的。這也沒有什么好報怨的,不是嗎?

  3、 從性能方面來考慮,這種方案也是最優(yōu)的,因為所有的策略都是發(fā)生在客戶端的,省去了第1、2種方案由服務(wù)器來管理帶來的瓶頸。

  因此,我們選擇了最后一種方案來做為JBOSS的集群策略。其實,只要大家再仔細回顧一下前面的部分,就會發(fā)現(xiàn)我們先前描述的方案不正是第3種方案嗎?但我們現(xiàn)在必須對這個策略在以下幾個方面做一些更深入的分析:

  1、 我們必須加入真正實現(xiàn)負載平衡的邏輯。

  2、 當客戶端發(fā)出調(diào)用時,我們應(yīng)該能夠決定到底將它發(fā)送到哪個服務(wù)器節(jié)點上。

  3、 我們希望為客戶端代理對像設(shè)計一個比較合適的服務(wù)器結(jié)點的拓撲圖,以便我們做出好的集群策略。


  負載平衡的設(shè)計策略

  前面已經(jīng)說過,JBOSS的負載平衡與失效轉(zhuǎn)發(fā)策略是由最后一個攔截器實現(xiàn)的(上圖中的①),然而我們要考慮的是雖然客戶端只發(fā)出一個調(diào)用,但針對于代理對像的調(diào)用可能包含多個可用的服務(wù)器結(jié)點,其個數(shù)等于集群中所有有效節(jié)點之和(參見上圖中的②),那么到底是由誰來決定這個策略的呢?這個工作由一個叫插件式的負載平衡策略來實施的(在下一段中簡稱策略①,如下圖)。



  當客戶端調(diào)用到達最后一個攔截器的時候,攔截器會請求策略①來為它選擇一個服務(wù)器結(jié)點。如果此結(jié)點有效且調(diào)用成功,則結(jié)果會返回給代理對像,如果失敗了,攔截器不會直接將錯誤返回給代理對像,而是將這個錯誤信息報告給策略①,并請求它再為客戶端選擇一個新節(jié)點。

  但還有一個問題值得考慮的,就是對一些致命性錯誤的處理。例如某個數(shù)據(jù)庫服務(wù)器突然崩潰了,那么最后一個攔截器將無法對此進行失效轉(zhuǎn)發(fā)了,因為不管選擇哪個服務(wù)器結(jié)點都不能解決這個問題了,在這里攔截器會將錯誤報告給客戶端,并由其自已做出決定。

  IT界里好像有這樣一個原理,就是"越是可擴展性強,靈活的東西實施起來就越復(fù)雜"。在JBOSS中也不例外,但幸運的是這些工作并沒為給客戶端帶來額外的編程負擔(dān),因為所有策略的配置都是在服務(wù)器完成的。
JBOSS的集群配置遵循XML規(guī)范,下面是的一個普通EJB對像的典型集群配置:

 

<jboss>
 <enterprise-beans>
 ?。約ession>
  ?。糴jb-name>MySessionBean</ejb-name>
  ?。糲lustered>True</clustered>
   <cluster-config>
   ?。紁artition-name>DefaultPartition</partition-name>
   ?。糷ome-load-balance-policy >
     org.jboss.ha.framework.interfaces.RoundRobin
   ?。?home-load-balance-policy>
   ?。糱ean-load-balance-policy>
     org.jboss.ha.framework.interfaces.FirstAvailable
   ?。?bean-load-balance-policy>
  ?。?cluster-config>
 ?。?session>
?。?enterprise-beans>
</jboss>

  上述配置說明了一個名為MySessionBean的會話Bean的集群策略,它定義了名為DefaultPartion的缺省策略名稱,并定義了2個具體的策略。當然,如果你覺得它比較復(fù)雜,而只想用JBOSS缺省的集群策略的話,可以將整個<cluster-config>標簽去掉。

  最后還有一個小問題值得考慮:由于集群策略是發(fā)生在客戶端的,當客戶端發(fā)出調(diào)用請求時,它不得不下載它的代理對像、攔截器、負載平衡策略等等。如果要下載的內(nèi)容過多,會影響客戶端的調(diào)用速度,這里JBOSS采取了一種延遲下載的方法,就是每次只下載一個必須的類,而不是一次全部下載,這樣就能使性能得到較大的改善。


  服務(wù)器結(jié)點拓撲圖的刷新

  JBOSS的集群實現(xiàn)是動態(tài)的,也就是說你可以動態(tài)地往集群中加入一個新節(jié)點或關(guān)閉任意一個節(jié)點,而不用費力地維護一張靜態(tài)的拓撲圖,就好像是JBOSS自己有能力管理集群一樣。這個思想夠先進吧?但與此同時它也帶來了一些令人頭痛的問題,請先看下圖:



  由于JBOSS的集群策略是在客戶端進行的,那么客戶端在調(diào)用EJB的時候會將所有必須的組件下載下來,然后由其進行集群決策。如果我們設(shè)T為時間,且t0<t1<t2,那么當處于t0時刻時,集群拓撲圖中包含server1和server2兩個節(jié)點,客戶端的調(diào)用被轉(zhuǎn)發(fā)到了結(jié)點2上。當處于t1時刻時,server1和server2全部都崩潰了。當處于t2時刻時,管理員增加了server3和server4兩個節(jié)點,但客戶端的拓撲圖中還只是包含原先的server1和server2兩節(jié)點的信息,因為它無法知道這新加入的2個節(jié)點。

  為了解決這個問題,JBOSS是這樣設(shè)計的,在客戶端的每次對某個節(jié)點調(diào)用后,服務(wù)器節(jié)點自動檢查客戶的拓撲圖是不是最新的,如果不是,則向客戶端發(fā)送新的拓撲圖,如下圖所示:



  當客戶端進行調(diào)用時,代理對像對其進行了一個小小的包裝,它將系統(tǒng)級調(diào)用invocation和自已現(xiàn)在的拓撲圖(JBOSS開發(fā)者稱它為view ID)發(fā)送到服務(wù)端,而服務(wù)端則檢查它自己的view ID是否與代理對像中的view ID吻合。這里我們先簡單介紹一下view ID,它實際上就是包含所有服務(wù)器節(jié)點的一個哈希表,至于為什么要用哈希表是因為它生成方便(java編譯器自帶)、存取快速,無須考慮排序問題。

  下面接著講述,如果代理對像的view ID與服務(wù)端節(jié)點的view ID相吻合的話,服務(wù)端將直接把結(jié)果傳給EJB對像,并將結(jié)果返回。

  如果服務(wù)器集群拓撲產(chǎn)生了變化,則會導(dǎo)致它們不吻合。這時服務(wù)器節(jié)點同樣也將調(diào)用EJB對像,但此時返回的結(jié)果有所不同,它除了返回客戶端的結(jié)果外,還要為代理對像返回一個最新的view ID,并通知代理對像:"喂,你的拓撲圖太舊了,我發(fā)了份新的,你趕快更新一下吧!" 當代理對像收到這個消息后會更新自己的view ID,并將結(jié)果返回客戶端代碼。

 

  性能考慮

  對于JBOSS來說,實現(xiàn)負載平衡與失效轉(zhuǎn)發(fā)所帶來的性能上的損失是很難計算的,因為它只發(fā)生在客戶端上,而每個客戶端不管從硬件配置、操作系統(tǒng)來說都是不一樣的。

  由于本文講的主要是對于無狀態(tài)的EJB對像的集群,但如果是有狀態(tài)的EJB或?qū)嶓wEJB,那情況會怎樣呢?答案是:情況只會更糟!為此服務(wù)器節(jié)點不得不進行狀態(tài)復(fù)制,而這個開銷通常是很大的,取決于狀態(tài)中上下文的內(nèi)容和狀態(tài)更新的頻率。所幸的是,對于大多數(shù)應(yīng)用而言,它們主要是進行無狀態(tài)的EJB調(diào)用,這樣就不服務(wù)器節(jié)點就不需進行大量狀態(tài)復(fù)制了。

  結(jié)論

  JBOSS為J2EE應(yīng)用提供了一個非常靈活有效的集群機制。它能使得在保持服務(wù)端性能損失最小的情況下進行失效轉(zhuǎn)發(fā),并能動態(tài)地對集群節(jié)點進行配置。更令人振奮的是,在JBOSS4.0中,集群機制將會發(fā)揮到極致,到時候就不僅僅是J2EE應(yīng)用能夠進行集群管理了,連普通的J2SE應(yīng)用都能進行集群了,到那時高可用性的計算并不只是一句口號了,而是JBOSS的一個簡單實現(xiàn)!

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多