1. 程式人生 > 其它 >JBoss 4.0.2叢集指南

JBoss 4.0.2叢集指南

JBoss 4.0.2叢集指南

本文主要講解JBoss cluster的基本知識以及簡單的配置方法,其間涉及了一些Jboss的補充知識。

一、材料準備:

1JBoss 4.0.2

JBoss各個版本之間差異比較大,即使同為JBoss4.x的版本,內部元件的版本也不一致,所以請儘量使用同一版本的server。目前已經證明可以配置cluster的版本多為JBoss 3.2.6JBoss 4.0.2

2Apache 2.0.54

3Apache mod_jk-1-2-13-apache-2-0-54

二、安裝:

1jboss4.0.2apache 2.0.54的安裝請自行搞定。假設JBoss

的安裝目錄為%jboss%apache安裝目錄為%apache%

2mod_jk的安裝。

apache.org獲得檔案mod_jk-1-2-13-apache-2-0-54.so,將該檔案拷貝到%apache%\modules

三、JBoss cluster入門

Jboss支援如下型別的clusterEJBwebJNDIJMS,我們主要了解webclusterWebcluster實際上可以劃分為兩個話題:負載均衡 (load balance) 和狀態同步。它們是互相獨立的,單獨配置。

負載均衡的概念比較簡單,重要的是負載均衡的粒度。可以選擇針對每個request的均衡,或者是針對每個使用者的均衡。選擇不同的粒度,需要不同的狀態同步方式。


1、基於request的負載均衡

該種方式下,負載均衡器(loadbalancer)會根據各個node的狀況,把每個httprequest進行分發。使用這樣的均衡策略,就必須在多個node之間複製使用者的session,實時保持整個cluster的使用者狀態同步,這種操作被稱為session複製(sessionreplication)Jboss的實現原理是使用攔截器(interceptor),根據使用者的同步策略攔截request,做同步處理後再交給server產生響應。

該方法的優點是客戶不會被繫結都具體的node,只要還有一個node存活,使用者狀態都不會丟失,cluster都能夠繼續工作。缺點是
node之間通訊頻繁,響應速度有影響,多併發、高頻操作的情況下效能下降比較厲害。


2、 基於使用者的負載均衡

該種方式下,當用戶發出第一個request後,負載均衡器動態的把該使用者分配到某個節點,並記錄該節點的jvm路由,以後該使用者的所有request都會被繫結這個jvm路由,使用者只會與該server發生互動,這種策略被稱為粘性session(sessionsticky)。該方法的優點是響應速度快,多個節點之間無須通訊。缺點也很明顯,某個node死掉以後,它負責的所有使用者都會丟失session

四、實戰

1、負載均衡

Jboss的負載均衡目前有兩種方案,一是使用apachemod_jk,二是使用JBoss自帶的負載均衡模組。下面分別講解這兩種配置。

mod_jk的配置

1、 請確認%apache%\modules下已經有mod_jk-1-2-13-apache-2-0-54.so檔案。

2、 修改%apache%\conf\httpd.conf在檔案末尾新增:

Include conf/mod_jk2.conf



3、 在%apache%\conf下新建檔案mod_jk2.conf檔案內容如下:

# Load mod_jk module. Specify the filename

# of the mod_jk lib you’ve downloaded and

# installed in the previous section

LoadModule jk_module modules/mod_jk-1-2-13-apache-2-0-54.so

# Where to find workers.properties

JkWorkersFile conf/workers2.properties

# Where to put jk logs

JkLogFile logs/mod_jk.log

# Set the jk log level [debug/error/info]

JkLogLevel info

# Select the log format

JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "

# JkOptions indicate to send SSL KEY SIZE,

JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories

# JkRequestLogFormat set the request format

JkRequestLogFormat "%w %V %T"

JkMount /* loadbalancer



其中

JkMount /* loadbalancer



的意思是,把所有的請求都發給loadbalancer處理。可以通過修改url來控制傳送某些request

4、 在 %apache%\conf下新建檔案workers2.properties其內容為:

worker.list=loadbalancer,server1,server2

# Define the first node...

worker.server1.port=8009

worker.server1.host=172.16.0.116

worker.server1.type=ajp13

worker.server1.lbfactor=1

worker.server1.local_worker=1

worker.server1.cachesize=10

 

# Define the first node...

worker.server2.port=8009

worker.server2.host=172.16.32.88

worker.server2.type=ajp13

worker.server2.lbfactor=1

worker.server2.local_worker=1

worker.server2.cachesize=10

 

# Now we define the load-balancing behaviour

worker.loadbalancer.type=lb

worker.loadbalancer.balanced_workers=server1,server2

worker.loadbalancer.sticky_session=1


其中對於node的命名規則是worker.節點名.xxxx

所以上述檔案定義了兩個節點:server1server28009埠是jboss預設的ajp埠,另外需要注意的是worker.server2.lbfactor引數,它是節點的負載加權,它的值越大,獲得負載的機會就越大。可以根據node的硬體效能進行調整。worker.loadbalancer.sticky_session引數是指定是否使用粘性session。所有需要負載均衡的節點,都必須在worker.loadbalancer.balanced_workers引數中列舉出來。請記住所有node的名稱和它對應著哪臺機器,後面的配置中會使用。嘗試啟動apache%apache\bin\apache.exe,正常情況下沒有任何提示。如果你使用的jk2.0的,那麼配置檔案的寫法完全不同,由於mod_jk2已經停止開發,所以apache並沒有提供任何講解,對於配置檔案的編寫也沒有任何指導。 Jboss自帶均衡器的配置

將資料夾%jboss%\docs\examples\varia\loadbalancer\loadbalancer.sar拷貝到%jboss%\server\all\d eploy下,並且修改loadbalancer.sar\loadbalancer.sar\META-INF\jboss-service.xml,在

<host>



標籤中類出所有節點,在

<sticky-session>



標籤中指定是否使用粘性session。配置完成。該均衡器的缺點是負載能力相對不高,配置引數太少,比如無法指定不同節點的負載加權,所以後面都以mod_jk為例,不再講解jboss自帶的負載均衡器的內容。負載均衡的配置基本完成,啟動jboss,其中過程中會列出DefaultPatition中所有的節點:

run.bat -c all





任何節點的關閉與啟動都會在cluster中廣播,比如加如一個新節點後,其他節點會得到以下提示:





2session sticky配置

apache應該會以粘性session的方式分發請求。部署一個應用測試一下,你會發現粘性session沒有起作用。因為我們還沒有給jboss配置jvm路由(jvmRoute)apache就無法知道究竟哪些session是屬於哪個節點的。我們繼續往下:修改server1機器上的jboss的配置檔案:%jboss%\server\all\deploy\jbossweb-tomcat55.sar\ META-INF\ jboss-service.xml110行有:

<attribute name="UseJK">false</attribute>



,將它改為true。值得注意的是在這行標籤上面有一段註釋,要求你在server.xml中必須有:Enginename="jboss.web"jmvRoute="Node1"defaultHost="localhost"請注意這裡有一個氣死人不償命的小bugjboss的官方文件把jvmRoute寫成了jmvRoute,就是vm兩個字母的顛倒讓我鬱悶了三天,翻遍了jboss.comtheserverside.com。都是直接拷貝的錯,吐血吐到脫水啊。

下面需要修改server1上的%jboss%\server\all\deploy\jbossweb-tomcat55.sar\ server.xml,在32行左右有:

<Engine name="jboss.web" defaultHost="localhost">



給它增加一個jvmRoute屬性:

<Engine jvmRoute="server1" name="jboss.web"defaultHost="localhost">



請注意,jvmRoute的值必須和mod_jk中的節點名字正確對應,否則無法正確路由。Cluster中的所有節點都應該做相應的配置。Jboss的配置完成了,下面需要在你的web應用中修改配置檔案,讓它支援叢集。在WEB-INF\web.xml中加入屬性:

<distributable/>



Ok,基於使用者的cluster完成了,每個使用者會繫結都某個節點上進行互動。這種繫結是如何完成的呢?原

apache把客戶分發到節點後,該節點會在使用者的sessionid後面加上此節點的路由名稱,變成這個樣子:Efdfxxd98daja87daj76da2dka**,server1有了這個標誌,就能分辨該session屬於哪個節點。

3session replication配置

下面要做的是基於requestcluster,也就讓各個節點之間互相複製session狀態。有兩種複製模式,同步與非同步。使用同步的方式,jboss會把session複製的操作和對request的響應放到一個應用事務(applicationtransaction)session複製完成後才去處理request

非同步複製則傳送session複製的訊息後馬上處理requestsession複製則會稍有延遲。但是在多框架的web頁面中,這樣的叢集方式會有問題。由於frame在同一時間發出多個request,會造成一些混亂,這也是採用基於使用者的叢集方式的原因之一。

JBoss4.0.2中採用了Jbosscache來實現session複製,實際上就是一個分散式快取,由於sessionid中包含了jvmroute,所以能夠分辨session屬於哪個節點。Session的更新類似於hibernate中的樂觀鎖,有了更新之後就讓session的版本號增加,其他節點通過對比版本號來決定是否同步session狀態。配置session replication首先需要編輯%jboss%server\all\deploy\jbossweb-tomcat55.sar\META-INF\ jboss-service.xml88行左右有:

<attribute name="SnapshotMode">instant</attribute>



這就是剛才提到的複製模式,instant為立即複製,如果設為interval那麼系統會在延遲一段時間再進行復制,時間長度在

<attribute name="SnapshotInterval">2000</attribute>

中指定,單位是毫秒。單獨配置這一個地方還不夠,在%jboss%server\all\deploy\ tc5-cluster-service.xml中有:

<attribute name="CacheMode">REPL_ASYNC</attribute>



這裡才真正決定複製是同步的還是非同步的,可以指定為REPL_ASYNC(非同步)或者REPL_SYNC(同步)。在這個檔案下面一點,還有一個config標籤,裡面指定了各個節點在進行session複製的時候如何通訊,有udptcp兩種可選,如果使用udp方式,那麼應該將udplookback屬性指定為true,因為windows上有一個叫做mediasense的東西會影響udpmulticast。注意如果你不瞭解multiaddressip規則,請不要隨便修改mcast_addr的值。如果採用tcp方式的話,應該指定bind_addr的值為本機ip,並且在TCPPING標籤的initial_hosts屬性中列出所有節點,格式是機器名[埠號]”,比如在我們的例子中,就應該這樣配置tcp(以其中一個節點為例)

<config>

<TCP bind_addr="172.16.0.116" start_port="7810" loopback="true"/>

<TCPPING initial_hosts="172.16.0.116[7810],172.16.32.88[7810]"

    port_range="3"timeout="3500"num_initial_members="3" up_thread="true"

    down_thread="true"/>

<MERGE2 min_interval="5000" max_interval="10000"/>

<FD shun="true" timeout="2500" max_tries="5" up_thread="true" down_thread="true" />

<VERIFY_SUSPECT timeout="1500" down_thread="false" up_thread="false" />

<pbcast.NAKACK down_thread="true" up_thread="true" gc_lag="100"

         retransmit_timeout="3000"/>

<pbcast.STABLE desired_avg_gossip="20000" down_thread="false" up_thread="false" />

<pbcast.GMS join_timeout="5000" join_retry_timeout="2000" shun="false"

    print_local_addr="true" down_thread="true" up_thread="true"/>

<pbcast.STATE_TRANSFER up_thread="true" down_thread="true"/>

</config>



JBossclustering版主建議儘量使用udp。不過在Sobey內部,建議使用tcp方式,經測試可能有不明物體在影響udp通訊,導致Timeout異常。

%jboss%\server\all\deploy\cluster-service.xml中也有關於udptcp的配置資訊,在4.0以前版本的JBoss中,會以這個檔案為主配置,4.0以後都以tc5-cluster-service.xml為主配置。

Jboss的配置完成了,最後需要在web應用中增加配置資訊,控制session複製的粒度。在WEB-INF\ jboss-web.xml中增加以下內容:

  <replication-config>

    <replication-trigger>SET_AND_NON_PRIMITIVE_GET

  </replication-trigger>

    <replication-granularity>SESSION

  </replication-granularity>

    </replication-config>

  



其中replication-trigger是指定哪些操作引發session的版本更新,它的取值有:

  SET_AND_GET       

  SET_AND_NON_PRIMITIVE_GET

  SET



replication-granularity是複製粒度,可以取sessionattribute。如果取為attribute有可能導致複製失敗,這是目前版本的jbosscache的一個bug,等待修正。部署專案,測試,如果配置沒有問題,可以在%jboss%\0server\all\log\server.log中發現類似於這樣的資訊:

DEBUG [org.jboss.web.tomcat.tc5.session.JBossCacheManager] check to

see if needs to store and replicate session with id Im9-qpuaXppMS+xXwE3M+Q**.server1

DEBUG [org.jboss.web.tomcat.tc5.session.ClusteredSession] processSessionRepl(): session is

dirty. Will increment version from: 20 and replicate.



Session replication配置的成功率比較低,情況也很複雜,請仔細操作。

五、分散式熱部署(distributable hot deploy)

在一個節點很多的cluster中,如果部署應用的時候必須把程式檔案拷貝到每個機器上的話,那實在太愚蠢了,幸好通過all啟動的jboss自動支援分散式熱部署。把支援cluster的應用(通常需要打包成war檔案),放到%jboss%\server\all\farm下,那麼處於同一cluster中的其他節點會自動下載並且部署,jbo ss把這個稱為Farm deploy。如下圖:

 

Jms叢集的意義在於提升系統在處理訊息時的併發能力,建立這樣的叢集,有三個步驟:
  
  1、  配置jms訊息持久化所使用的資料庫
  
  2、  配置分散式的jndi環境
  
  3、  配置分散式jms
  
  在jboss 4.0.2中,系統採用hibernate的方式來儲存訊息,所以能夠相容hibernate支援的所有資料庫。Jboss預設採用hsql,在我們的例子中,將使用oracle 9.2。首先需要配置連線到資料庫的jndi資料來源。方法是把doc\examples\jca下的oracle-ds.xml檔案拷貝到server\all\farm下,並且修改其中的引數,保證資料庫能夠正確連線。Cluster啟動後,該檔案能夠通過jbossfarm服務,自動拷貝到其他叢集節點,並且自動部署。假設jndi資料來源的名稱為:GlobalDS
  
  將doc\examples\jms下的oracle-jdbc3-service.xml檔案拷貝到server\all\deploy-hasingleton\jms目錄下,並且刪除該目錄下的hsqldb-jdbc2-service.xml。修改oracle-jdbc3-service.xml,在56行左右指定name的值為資料來源的名字:GlobalDS。這樣系統會使用該資料來源來儲存jms訊息。使用如下命令啟動boss:  run ?c all
  
  啟動完成後,正常情況下會發現oracle資料庫中多出了三張表:
  
  1Jms_message_log    該表用於儲存所有未處理的點對點訊息,表結構是:
  
  Messageid     訊息id
  
  Destination    目的地
  
  Txid      事務id
  
  Txop      訊息操作型別(a為新增,d為刪除)
  
  Messageblob    訊息內容
  
  2JMS_REFERENCE_LOG  用於儲存所有未處理的topic訊息,表結構是:
  
  Messageid
  
  Destination
  
  Txid
  
  Txop
  
  Messageblob
  
  Redelivered    訊息是否被重發
  
  3JMS_TRANSACTION_LOG  用於儲存處理訊息過程中的一些重要的事務
  
  需要注意的是,jboss 3.2之後就不在支援以檔案形式儲存訊息,雖然這樣最會比資料庫操作快一倍以上。Jboss官方的解釋是,使用檔案會讓系統不可靠。
  
  客戶端在傳送jms訊息的時候,首先需要向app server查詢jndi,在jboss cluster中,jndi是作為一個分散式的singleton出現的。每個節點除了有自己的jndi環境以外,整個cluster還具有一些全域性的jndi,客戶端在進行jndi查詢的時候,只需要向這個全域性的jndi進行查詢,cluster如果在全域性jndi中找不到對應的jndi物件,就會按次序向每個節點詢問,看他們的本地jndi中是否有匹配的物件,如果有則返回給客戶,如果所有的節點都沒有,則丟擲異常。所有以all方式啟動的jboss,都會開啟1100埠,這個埠是全域性jndi的入口,所有節點都是如此。
  
  分散式的jndi有的節點有主次的區別,第一個啟動的jboss是主伺服器,它會儲存所有的全域性jndi,其他的節點如果收到客戶查詢jndi的請求後,都會向主伺服器請求資料。如果主伺服器不幸down掉,那麼次節點會發現這個變化,然後啟動自己的jndi環境,取代主伺服器提供服務。
  
  下面是配置jmsjndi,開啟server\all\deploy-hasingleton\jms下的jbossmq-destinations-service.xml檔案,增加一個名為testdestination,如下:
  
  <mbean code="org.jboss.mq.server.jmx.Queue"
  
  name="jboss.mq.destination:service=Queue,name=test">
  
  <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
  
  </mbean>
  
  為了預防主伺服器down了之後丟失該jndi,所以最好在每個節點都進行這個配置。
  
  在jboss 4.0.2的預設配置下,是不支援訊息bean的叢集的,要達到這個目的,必須下載一個jar包才能實現,可以從這裡獲得: http://blog.yam.com/bromon/archives/489460.html
  
  得到這個jar檔案後,將它命名為cdot-jbossx.jar
  
  檔案放到server\all\deploy\jms下。下面編寫訊息bean,它的功能很簡單,接收到來自test佇列的訊息後,列印訊息id
  
  public class TestJmsBean
  
  implements MessageDrivenBean, MessageListener {
  
  MessageDrivenContext messageDrivenContext;
  
  public void ejbCreate() {
  
  System.out.println("訊息bean建立");
  
  }
  
  public void ejbRemove() {
  
  }
  public void onMessage(Message msg) {
  
  try
  
  {
  
  System.out.println(msg.getJMSMessageID());
  
  }catch(Exception e)
  
  {
  
  e.printStackTrace();
  
  }
  
  }
  public void setMessageDrivenContext(MessageDrivenContext messageDrivenContext) {
  
  this.messageDrivenContext = messageDrivenContext;
  
  }
  
  }
  
  把這個訊息bean部署到server\all\farm目錄下,它會被自動拷貝到cluster的其它節點,並且被自動部署,你會看到如下部署資訊:
  


  上面顯示通過farm的方式,部署了一個名為GlobalDS的連線池,以及一個名為TestJms的訊息bean
  
  下面寫個客戶端來測試一下:
  
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  
  Properties p = new Properties();
  
  p.put(Context.INITIAL_CONTEXT_FACTORY,
  
  "org.jnp.interfaces.NamingContextFactory");
  p.put(Context.URL_PKG_PREFIXES, "jboss.naming:org.jnp.interfaces");
  
  p.put(Context.PROVIDER_URL, "172.16.0.116:1100"); // 全域性jndi入口
  
  InitialContext ctx = new InitialContext(p);
  
  QueueConnectionFactory qcf = (QueueConnectionFactory) ctx.lookup(
  
  "ConnectionFactory");
  
  QueueConnection conn = qcf.createQueueConnection();
  
  Queue q = (Queue) ctx.lookup("queue/test");//查詢名為testdestination
  
  QueueSession session = conn.createQueueSession(false,
  
  QueueSession.AUTO_ACKNOWLEDGE);
  
  conn.start();
  
  QueueSender sender = session.createSender(q);
  
  for (int i = 0; i < 10000; i++) {
  
  TextMessage tm = session.createTextMessage(sdf.format(new Date()));
  
  sender.send(tm, DeliveryMode.PERSISTENT, 4, 0);//傳送持久化訊息
  
  System.out.print("" + i);
  
  }
  
  conn.stop();
  
  session.close();
  
  conn.close();
  
  執行一下,可以看到每個節點都建立了若干個訊息bean,同時在處理訊息,任意關閉一個次伺服器,系統會自動fail over。檢視Jms_message_log資料表,裡面沒有任何資料,表示所有的訊息都已經被處理。
  
  Jbossjms cluster功能與websphere mq比較起來,是非常簡陋的,可以配置的地方也很少,畢竟是免費的東西。Jboss的論壇上透露,在jboss 6.0中將會有全新的jboss messaging服務,不知要等到何年何月。針對這個cluster,我做過簡單的測試,800萬左右的訊息數量,無一丟失,應該說還算比較可靠。響應時間也還過的去,在簡單的網路環境下,能夠應付比較高的併發。