JBoss 4.0.2集群指南(二)
建立JMS集群服務(wù)
bromon原創(chuàng) 請(qǐng)尊重版權(quán)
本問(wèn)講解如何在jboss 4.0.2中建立jms消息集群服務(wù)器,本文以《jboss 4.0.2集群指南》為基礎(chǔ),請(qǐng)參照閱讀。(http://blog.yam.com/bromon/archives/454467.html)
Jms集群的意義在于提升系統(tǒng)在處理消息時(shí)的并發(fā)能力,建立這樣的集群,有三個(gè)步驟:
1、 配置jms消息持久化所使用的數(shù)據(jù)庫(kù)
2、 配置分布式的jndi環(huán)境
3、 配置分布式j(luò)ms
在jboss4.0.2中,系統(tǒng)采用hibernate的方式來(lái)保存消息,所以能夠兼容hibernate支持的所有數(shù)據(jù)庫(kù)。Jboss默認(rèn)采用hsql,在我們的例子中,將使用oracle9.2。首先需要配置連接到數(shù)據(jù)庫(kù)的jndi數(shù)據(jù)源。方法是把doc\examples\jca下的oracle-ds.xml文件拷貝到server\all\farm下,并且修改其中的參數(shù),保證數(shù)據(jù)庫(kù)能夠正確連接。Cluster啟動(dòng)后,該文件能夠通過(guò)jboss的farm服務(wù),自動(dòng)拷貝到其他集群節(jié)點(diǎn),并且自動(dòng)部署。假設(shè)jndi數(shù)據(jù)源的名稱為:GlobalDS將doc\examples\jms下的oracle-jdbc3-service.xml文件拷貝到server\all\deploy-hasingleton\jms目錄下,并且刪除該目錄下的hsqldb-jdbc2-service.xml。修改oracle-jdbc3-service.xml,在56行左右指定name的值為數(shù)據(jù)源的名字:GlobalDS。這樣系統(tǒng)會(huì)使用該數(shù)據(jù)源來(lái)保存jms消息。
使用如下命令啟動(dòng)boss: run –c all
啟動(dòng)完成后,正常情況下會(huì)發(fā)現(xiàn)oracle數(shù)據(jù)庫(kù)中多出了三張表:
1、Jms_message_log 該表用于保存所有未處理的點(diǎn)對(duì)點(diǎn)消息,表結(jié)構(gòu)是:
Messageid 消息id
Destination 目的地
Txid 事務(wù)id
Txop 消息操作類型(a為新增,d為刪除)
Messageblob 消息內(nèi)容
2、JMS_REFERENCE_LOG 用于保存所有未處理的topic消息,表結(jié)構(gòu)是:
Messageid
Destination
Txid
Txop
Messageblob
Redelivered 消息是否被重發(fā)
3、JMS_TRANSACTION_LOG 用于保存處理消息過(guò)程中的一些重要的事務(wù)
需要注意的是,jboss 3.2之后就不在支持以文件形式保存消息,雖然這樣最會(huì)比數(shù)據(jù)庫(kù)操作快一倍以上。Jboss官方的解釋是,使用文件會(huì)讓系統(tǒng)不可靠。
客戶端在發(fā)送jms消息的時(shí)候,首先需要向app server查詢jndi,在jbosscluster中,jndi是作為一個(gè)分布式的singleton出現(xiàn)的。每個(gè)節(jié)點(diǎn)除了有自己的jndi環(huán)境以外,整個(gè)cluster還具有一些全局的jndi,客戶端在進(jìn)行jndi查詢的時(shí)候,只需要向這個(gè)全局的jndi進(jìn)行查詢,cluster如果在全局jndi中找不到對(duì)應(yīng)的jndi對(duì)象,就會(huì)按次序向每個(gè)節(jié)點(diǎn)詢問(wèn),看他們的本地jndi中是否有匹配的對(duì)象,如果有則返回給客戶,如果所有的節(jié)點(diǎn)都沒(méi)有,則拋出異常。所有以all方式啟動(dòng)的jboss,都會(huì)打開(kāi)1100端口,這個(gè)端口是全局jndi的入口,所有節(jié)點(diǎn)都是如此。
分布式的jndi有的節(jié)點(diǎn)有主次的區(qū)別,第一個(gè)啟動(dòng)的jboss是主服務(wù)器,它會(huì)保存所有的全局jndi,其他的節(jié)點(diǎn)如果收到客戶查詢jndi的請(qǐng)求后,都會(huì)向主服務(wù)器請(qǐng)求數(shù)據(jù)。如果主服務(wù)器不幸down掉,那么次節(jié)點(diǎn)會(huì)發(fā)現(xiàn)這個(gè)變化,然后啟動(dòng)自己的jndi環(huán)境,取代主服務(wù)器提供服務(wù)。
下面是配置jms的jndi,打開(kāi)server\all\deploy-hasingleton\jms下的jbossmq-destinations-
service.xml文件,增加一個(gè)名為test的destination,如下:
name="DestinationManager">jboss.mq:service=DestinationManager
為了預(yù)防主服務(wù)器down了之后丟失該jndi,所以最好在每個(gè)節(jié)點(diǎn)都進(jìn)行這個(gè)配置。
在jboss 4.0.2的默認(rèn)配置下,是不支持消息bean的集群的,要達(dá)到這個(gè)目的,必須下載一個(gè)jar包才能實(shí)現(xiàn),可以從這里獲得: http://blog.yam.com/bromon/archives/489460.html
得到這個(gè)jar文件后,將它命名為cdot-jbossx.jar 文件放到server\all\deploy\jms下。下面編寫消息bean,它的功能很簡(jiǎn)單,接收到來(lái)自test隊(duì)列的消息后,打印消息id。
public class TestJmsBean
implements MessageDrivenBean, MessageListener {
MessageDrivenContext messageDrivenContext;
public void ejbCreate() {
System.out.println("消息bean創(chuàng)建");
}
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;
}
}
把這個(gè)消息bean部署到server\all\farm目錄下,它會(huì)被自動(dòng)拷貝到cluster的其它節(jié)點(diǎn),并且被自動(dòng)部署,你會(huì)
看到如下部署信息:
上面顯示通過(guò)farm的方式,部署了一個(gè)名為GlobalDS的連接池,以及一個(gè)名為TestJms的消息bean。
下面寫個(gè)客戶端來(lái)測(cè)試一下:
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");//查詢名為test的destination
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);//發(fā)送持久化消息
System.out.print("第" + i);
}
conn.stop();
session.close();
conn.close();
執(zhí)行一下,可以看到每個(gè)節(jié)點(diǎn)都創(chuàng)建了若干個(gè)消息bean,同時(shí)在處理消息,任意關(guān)閉一個(gè)次服務(wù)器,系統(tǒng)會(huì)自動(dòng)fail over。查看Jms_message_log數(shù)據(jù)表,里面沒(méi)有任何數(shù)據(jù),表示所有的消息都已經(jīng)被處理。
Jboss的jms cluster功能與webspheremq比較起來(lái),是非常簡(jiǎn)陋的,可以配置的地方也很少,畢竟是免費(fèi)的東西。Jboss的論壇上透露,在jboss 6.0中將會(huì)有全新的jbossmessaging服務(wù),不知要等到何年何月。針對(duì)這個(gè)cluster,我做過(guò)簡(jiǎn)單的測(cè)試,800萬(wàn)左右的消息數(shù)量,無(wú)一丟失,應(yīng)該說(shuō)還算比較可靠。響應(yīng)時(shí)間也還過(guò)的去,在簡(jiǎn)單的網(wǎng)絡(luò)環(huán)境下,能夠應(yīng)付比較高的并發(fā)。