Jms集群的意義在於提升系統在處理消息時的並發能力
建立這樣的集群
有三個步驟
配置jms消息持久化所使用的數據庫
配置分布式的jndi環境
配置分布式jms
在jboss
中
系統采用hibernate的方式來保存消息
所以能夠兼容hibernate支持的所有數據庫
Jboss默認采用hsql
在我們的例子中
將使用oracle
首先需要配置連接到數據庫的jndi數據源
方法是把doc\examples\jca下的oracle
ds
xml文件拷貝到server\all\farm下
並且修改其中的參數
保證數據庫能夠正確連接
Cluster啟動後
該文件能夠通過jboss的farm服務
自動拷貝到其他集群節點
並且自動部署
假設jndi數據源的名稱為
GlobalDS
將doc\examples\jms下的oracle
jdbc
service
xml文件拷貝到server\all\deploy
hasingleton\jms目錄下
並且刪除該目錄下的hsqldb
jdbc
service
xml
修改oracle
jdbc
service
xml
在
行左右指定name的值為數據源的名字
GlobalDS
這樣系統會使用該數據源來保存jms消息
使用如下命令啟動boss: run ?c all
啟動完成後
正常情況下會發現oracle數據庫中多出了三張表
Jms_message_log 該表用於保存所有未處理的點對點消息
表結構是
Messageid 消息id
Destination 目的地
Txid 事務id
Txop 消息操作類型(a為新增
d為刪除)
Messageblob 消息內容
JMS_REFERENCE_LOG 用於保存所有未處理的topic消息
表結構是
Messageid
Destination
Txid
Txop
Messageblob
Redelivered 消息是否被重發
JMS_TRANSACTION_LOG 用於保存處理消息過程中的一些重要的事務
需要注意的是
jboss
之後就不在支持以文件形式保存消息
雖然這樣最會比數據庫操作快一倍以上
Jboss官方的解釋是
使用文件會讓系統不可靠
客戶端在發送jms消息的時候
首先需要向app server查詢jndi
在jboss cluster中
jndi是作為一個分布式的singleton出現的
每個節點除了有自己的jndi環境以外
整個cluster還具有一些全局的jndi
客戶端在進行jndi查詢的時候
只需要向這個全局的jndi進行查詢
cluster如果在全局jndi中找不到對應的jndi對象
就會按次序向每個節點詢問
看他們的本地jndi中是否有匹配的對象
如果有則返回給客戶
如果所有的節點都沒有
則拋出異常
所有以all方式啟動的jboss
都會打開
端口
這個端口是全局jndi的入口
所有節點都是如此
分布式的jndi有的節點有主次的區別
第一個啟動的jboss是主服務器
它會保存所有的全局jndi
其他的節點如果收到客戶查詢jndi的請求後
都會向主服務器請求數據
如果主服務器不幸down掉
那麼次節點會發現這個變化
然後啟動自己的jndi環境
取代主服務器提供服務
下面是配置jms的jndi
打開server\all\deploy
hasingleton\jms下的jbossmq
destinations
service
xml文件
增加一個名為test的destination
如下
<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
的默認配置下
是不支持消息bean的集群的
要達到這個目的
必須下載一個jar包才能實現
可以從這裡獲得:
得到這個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) {
ssageDrivenContext = messageDrivenContext;
}
}
把這個消息bean部署到server\all\farm目錄下
它會被自動拷貝到cluster的其它節點
並且被自動部署
你會看到如下部署信息
educitycn/img_///jpg > 上面顯示通過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
:
); // 全局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 =
; i <
; i++) {
TextMessage tm = session
createTextMessage(sdf
format(new Date()));
sender
send(tm
DeliveryMode
PERSISTENT
);//發送持久化消息
System
out
print(
第
+ i);
}
conn
stop();
session
close();
conn
close();
執行一下
可以看到每個節點都創建了若干個消息bean
同時在處理消息
任意關閉一個次服務器
系統會自動fail over
查看Jms_message_log數據表
裡面沒有任何數據
表示所有的消息都已經被處理
Jboss的jms cluster功能與websphere mq比較起來
是非常簡陋的
可以配置的地方也很少
畢竟是免費的東西
Jboss的論壇上透露
在jboss
中將會有全新的jboss messaging服務
不知要等到何年何月
針對這個cluster
我做過簡單的測試
萬左右的消息數量
無一丟失
應該說還算比較可靠
響應時間也還過的去
在簡單的網絡環境下
能夠應付比較高的並發
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28870.html