隨著計(jì)算機(jī)網(wǎng)絡(luò)和分布式應(yīng)用的不斷發(fā)展,遠(yuǎn)程消息傳遞越來越成為應(yīng)用系統(tǒng)中不可缺少的組成部分。商業(yè)消息中間件的出現(xiàn)保證了消息傳輸?shù)目煽啃裕咝屎桶踩裕瑫r(shí)也減少了系統(tǒng)的開發(fā)周期。目前應(yīng)用最多的消息中間件產(chǎn)品為IBM MQSeries。本文就針對(duì)MQ的基本操作與配置進(jìn)行詳細(xì)的闡述,希望對(duì)讀者有所幫助。 |
MQ中有幾個(gè)很重要的組件:隊(duì)列管理器(QueueManager)、隊(duì)列(Queue)和通道(Channel)。其基本的操作方法如下: |
-q是指創(chuàng)建缺省的隊(duì)列管理器 |
如果是啟動(dòng)默認(rèn)的隊(duì)列管理器,可以不帶其名字 |
endmqm –p QmgrName 強(qiáng)制停止 |
如果是默認(rèn)隊(duì)列管理器,可以不帶其名字 |
如果隊(duì)列是默認(rèn)隊(duì)列管理器中的隊(duì)列,可以不帶其隊(duì)列管理器的名字 |
如果隊(duì)列是默認(rèn)隊(duì)列管理器中的隊(duì)列,可以不帶其隊(duì)列管理器的名字 |
runmqchl –c ChlName –m QmgrName |
runmqlsr –t TYPE –p PORT –m QMgrName |
DEFINE QLOCAL(QNAME) DEFPSIST(YES) REPLACE |
設(shè)定隊(duì)列管理器的死信隊(duì)列 |
DEFINE QALIAS(QALIASNAME) TARGQ(QNAME) |
RNAME(AAA) RQMNAME(QMGRNAME) + |
DEFINE QMODEL(QNAME) DEFTYPE(TEMPDYN) |
DEFINE QLOCAL(QTNAME) USAGE(XMITQ) DEFPSIST(YES) + |
INITQ(SYSTEM.CHANNEL.INITQ)+ |
PROCESS(PROCESSNAME) REPLACE |
DEFINE PROCESS(PRONAME) + |
APPLICID(’ runmqchl -c SDR_TEST -m QM_ TEST’) |
其中APPLTYPE的值可以是:CICS、UNIX、WINDOWS、WINDOWSNT等 |
DEFINE CHANNEL(SDRNAME) CHLTYPE(SDR)+ |
CONNAME(‘100.100.100.215(1418)’) XMITQ(QTNAME) REPLACE |
其中CHLTYPE可以是:SDR、SVR、RCVR、RQSTR、CLNTCONN、SVRCONN、CLUSSDR和CLUSRCVR。 |
DEFINE CHANNEL(SDR_ TEST) CHLTYPE(RCVR) REPLACE |
DEFINE CHANNEL(SVRCONNNAME) CHLTYPE(SVRCONN) REPLACE |
DISPLAY QUEUE(QNAME) [ALL] |
DISPLAY QUEUE(QNAME) DESCR GET PUT |
DISPLAY QUEUE(QNAME)MAXDEPTH CURDEPTH |
ALTER QMGR DESCR(‘NEW DESCRIPTION’) |
ALTER QLOCAL(QNAME) PUT(DISABLED) |
ALTER QALIAS(QNAME) TARGQ(TARGQNAME) |
二.配置一個(gè)能夠通信的遠(yuǎn)程連接 |
以上講述了MQ的基本命令操作,但只知道這些是沒有實(shí)際意義的。MQ的最終目的是實(shí)現(xiàn)遠(yuǎn)程通信,所以下面就以一個(gè)具體的例子來說明如何實(shí)現(xiàn)遠(yuǎn)程連接。這個(gè)例子的目的是建立可以實(shí)現(xiàn)消息傳遞的一對(duì)MQ服務(wù)器,它們分別基于NT和UNIX平臺(tái)。 |
DEFINE QL(NT.DEADQ) DEFPSIST(YES) REPLACE |
更改隊(duì)列管理器屬性,設(shè)置其死信隊(duì)列 |
ALTER QMGR DEADQ(NT.DEADQ) |
APPLICID(’ runmqchl -c SDR_NT -m QM_NT’) |
DEFINE QL(QT_NT) USAGE(XMITQ) DEFPSIST(YES) + |
INITQ(SYSTEM.CHANNEL.INITQ)+ |
創(chuàng)建遠(yuǎn)程隊(duì)列定義,對(duì)應(yīng)于UNIX機(jī)器上的本地隊(duì)列Q_UNIX,傳輸隊(duì)列為QT_NT |
RNAME(Q_UNIX) RQMNAME(QM_UNIX)+ |
創(chuàng)建發(fā)送方通道,其傳輸隊(duì)列為QT_NT,遠(yuǎn)程主機(jī)地址為10.10.10.2,偵聽端口為1414 |
DEFINE CHANNEL(SDR_NT) CHLTYPE(SDR)+ |
CONNAME(‘10.10.10.2(1414)’) XMITQ(QT_NT) REPLACE |
DEFINE CHANNEL(S_NT) CHLTYPE(SVRCONN) REPLACE |
在UNIX端創(chuàng)建隊(duì)列管理器 |
MQSeries 1414/tcp #MQSeries channel listener |
修改/etc/inetd.conf文件,加入一行(啟動(dòng)偵聽程序) |
MQSeries stream tcp nowait mqm /usr/lpp/mqm/bin/amqcrsta amqcrsta –m QM_UNIX |
DEFINE QL(UNIX.DEADQ) DEFPSIST(YES) REPLACE |
更改隊(duì)列管理器屬性,設(shè)置其死信隊(duì)列 |
ALTER QMGR DEADQ(UNIX.DEADQ) |
創(chuàng)建接收方通道,其名字必須與遠(yuǎn)程發(fā)送方相同 |
DEFINE CHANNEL(SDR_NT) CHLTYPE(RCVR) REPLACE |
DEFINE QL(Q_UNIX) DEFPSIST(YES) REPLACE |
DEFINE CHANNEL(S_UNIX) CHLTYPE(SVRCONN) REPLACE |
經(jīng)過以上操作之后,遠(yuǎn)程連接的配置工作完成。接下來需要驗(yàn)證配置是否正確。 |
runmqchl –c SDR_NT –m QM_NT 或 start chl(SDR_NT) |
/usr/mqm/samp/bin/amqsget Q_UNIX QM_UNIX |
另,在NT下一般情況下在建立隊(duì)列管理器時(shí)會(huì)自動(dòng)建立偵聽器,啟動(dòng)隊(duì)列管理器時(shí)則會(huì)自動(dòng)啟動(dòng)偵聽程序。當(dāng)然也可以手動(dòng)配置偵聽程序。 |
修改\winnt\system32\drivers\etc\services文件,在文件中加入一行: |
MQSeries 1414/tcp #MQSeries channel listener |
runmqlsr –t tcp –p 1414 –m QM_NT |
以上說明了怎樣建立簡(jiǎn)單的單向傳輸網(wǎng)絡(luò)。消息從NT端傳送到UNIX端。建立從UNIX端到NT端的遠(yuǎn)程連接和以上相仿,要建立雙向的傳輸網(wǎng)絡(luò)也是同樣的道理。 |
用JMS實(shí)現(xiàn)消息的發(fā)送和接收時(shí),經(jīng)常會(huì)用到JNDI。因?yàn)镴NDI這種方式比較靈活,對(duì)于編程也比較簡(jiǎn)單。 |
在安裝了MQSeries Client for Java之后,在\java\bin目錄下找到JMSAdmin.config文件。該文件主要用來說明Context的存儲(chǔ)方式及存儲(chǔ)地址,對(duì)應(yīng)于文件中的兩個(gè)參數(shù)INITIAL_CONTEXT_FACTORY和PROVIDER_URL。典型的JMSAdmin.config文件內(nèi)容如下: |
#INITIAL_CONTEXT_FACTORY=com.sun.jndi.ldap.LdapCtxFactory |
INITIAL_CONTEXT_FACTORY=com.sun.jndi.fscontext.RefFSContextFactory |
#INITIAL_CONTEXT_FACTORY=com.ibm.ejs.ns.jndi.CNInitialContextFactory |
#PROVIDER_URL=ldap://polaris/o=ibm,c=us |
PROVIDER_URL=file:/d:/temp |
#PROVIDER_URL=iiop://localhost/ |
SECURITY_AUTHENTICATION=none |
INITIAL_CONTEXT_FACTORY表示JMSAdmin Tool使用的服務(wù)提供商。當(dāng)前有三種受支持的值。com.sun.jndi.ldap.LdapCtxFactory用于LDAP,如果使用它就必須安裝一個(gè)LDAP服務(wù)器。com.sun.jndi.fscontext.RefFSContextFactory用于文件系統(tǒng)上下文,它只需要使用者提供存放上下文的文件路徑。com.ibm.ejs.ns.jndi.CNInitialContextFactory是專門為websphere提供的,它需要和websphere的CosNaming資源庫(kù)一起使用。 |
PROVIDER_URL表示會(huì)話初始上下文的URL,由JMSAdmin tool實(shí)現(xiàn)的所有JNDI操作的根。它和INITIAL_CONTEXT_FACTORY一一對(duì)應(yīng)。 |
ldap://hostname/contextname 用于LDAP |
file:[drive:]/pathname 用于文件系統(tǒng)上下文 |
iiop://hostname[:port]/[?TargetContext=ctx] 用于訪問websphere CosNaming名稱空間 |
最后還有一個(gè)參數(shù)SECURITY_AUTHENTICATION,用于說明JNDI是否把安全性憑證傳遞給了您使用的服務(wù)供應(yīng)商。只有當(dāng)使用了LDAP服務(wù)供應(yīng)商時(shí),才使用此參數(shù)。此參數(shù)有三個(gè)值,none(匿名認(rèn)證)、simple(簡(jiǎn)單認(rèn)證)和CRAM-MD5認(rèn)證機(jī)制。如果沒有提供有效值,缺省值為none。 |
確認(rèn)配置文件之后,可以在\java\bin目錄下啟動(dòng)JMSAdmin控制臺(tái)。也可以在任何目錄下用下面的命令來啟動(dòng)控制臺(tái): |
JMSAdmin –cfg MQ_JAVA_INSTALL_PATH\java\bin\JMSAdmin.config |
其中MQ_JAVA_INSTALL_PATH為MQSeries Client for Java安裝的根目錄。 |
若啟動(dòng)失敗,則好好檢查一下您的環(huán)境變量是否設(shè)置正確。根據(jù)我個(gè)人的經(jīng)驗(yàn),除了把com.ibm.mq.jar和com.ibm.mqjms.jar加入到環(huán)境變量外,還要把fscontext.jar和providerutil.jar加入到環(huán)境變量。 |
進(jìn)入JMSAdmin控制臺(tái)后,您可以自由定義sub context。對(duì)于子上下文的操作,主要有一下命令: |
當(dāng)然,在這里的主要任務(wù)并非是用來定義sub context,而是用來定義以下幾個(gè)對(duì)象: |
(還有其它的一些對(duì)象,如MQXAQueueConnectionFactory等,不常用到,在此不作說明。) |
可以使用很多動(dòng)詞來操縱目錄名稱空間中的受管理對(duì)象。ALTER、DEFINE、DISPLAY、DELETE、COPY和MOVE,它們的用法都算比較簡(jiǎn)單,這里只列舉一二以作說明。 |
例一:定義一QueueConnectionFactory,連接主機(jī)10.10.10.18,端口1414 |
DESC(Example Queue Connection Factory)+ |
例二:定義一Queue,其對(duì)應(yīng)于MQ中的Q_EXAMPLE |
上面我們說明了怎樣用JMSAdmin Tool定義MQ對(duì)象的上下文。我們的最終目的是要用JMS來實(shí)現(xiàn)MQ編程,以實(shí)現(xiàn)在程序中對(duì)MQ隊(duì)列進(jìn)行收、發(fā)消息。所以,下面我們將重點(diǎn)討論一下MQ的JMS實(shí)現(xiàn)。 |
如果您對(duì)JMS編程很熟悉,那么您也就會(huì)用JMS來實(shí)現(xiàn)MQ編程,因?yàn)橛肑MS來編寫MQ程序與編寫一般的JMS程序沒有太大的差別。舉個(gè)例子,當(dāng)我們想發(fā)送一條消息到MQ的隊(duì)列中,再?gòu)脑撽?duì)列中取回消息時(shí),我們編程時(shí)主要有四個(gè)步驟。首先我們要初始化在程序中要用到的對(duì)象,然后才可以發(fā)送消息到隊(duì)列中去,再就是收取消息了,最后要清除那些永久對(duì)象。這些都和普通的JMS程序相當(dāng)。程序的源代碼如下: |
import java.util.Hashtable; |
import javax.naming.directory.*; |
protected QueueConnectionFactory factory=null; |
protected QueueConnection connection; |
protected QueueSession queueSession; |
protected TextMessage outMessage; |
protected QueueSender queueSender; |
protected QueueReceiver queueReceiver; |
public static final String qcfLookup="EXAMPLEQCF"; |
public static final String qLookup="EXAMPLEQL"; |
public static final String icf = "com.sun.jndi.fscontext.RefFSContextFactory"; |
public String url ="file:/d:/temp"; |
public void sampleInit() throws Exception { |
Hashtable environment = new Hashtable(); |
environment.put(Context.INITIAL_CONTEXT_FACTORY, icf); |
environment.put(Context.PROVIDER_URL, url); |
environment.put(Context.REFERRAL, "throw"); |
Context ctx=new InitialDirContext(environment); |
factory = (QueueConnectionFactory)ctx.lookup(qcfLookup); |
q1=(Queue)ctx.lookup(qLookup); |
connection = factory.createQueueConnection(); |
queueSession = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); |
queueSender = queueSession.createSender(q1); |
queueSender.setDeliveryMode(DeliveryMode.NON_PERSISTENT); |
outMessage = queueSession.createTextMessage(); |
queueReceiver = queueSession.createReceiver(q1); |
public void sendMessageOut(String message) throws JMSException { |
outMessage.setText(message); |
queueSender.send(outMessage); |
public String receiveMessage() throws Exception{ |
return ((TextMessage)queueReceiver.receive()).getText(); |
public void sampleClose() throws JMSException { |
public static void main(String[] args){ |
sample sp = new sample(); |
sp.sendMessageOut("Hello World!"); |
java.lang.Thread.sleep(4000); |
System.out.println("Receive text is : "+rec); |
MQ在WINDOWS平臺(tái)下具有圖形化管理界面,但在UNIX平臺(tái)下卻只能通過命令行來進(jìn)行操作。這樣就給使用者帶來很大的不便。我們都希望能通過圖形界面來進(jìn)行管理配置。為了實(shí)現(xiàn)我們的想法,我們就必須建立遠(yuǎn)程管理。 |
實(shí)現(xiàn)遠(yuǎn)程管理有以下幾個(gè)步驟: |
1.被管理隊(duì)列管理器上的命令隊(duì)列SYSTEM.ADMIN.COMMAND.QUEUE存在并可用。對(duì)于MQ 2版本應(yīng)執(zhí)行 amqscoma.tst 腳本來創(chuàng)建。 |
2.使用strmqcsv命令來啟動(dòng)被管理隊(duì)列管理器上的命令服務(wù)器。 |
3.確定被管理隊(duì)列管理器上的服務(wù)器連接通道SYSTEM.ADMIN.SVRCONN是否存在,如果不存在則創(chuàng)建它。 |
4.一般Unix、Linux平臺(tái)中MQ默認(rèn)的字符集為819,而Windows平臺(tái)為1381,所以你必須改變其字符集,使兩邊的字符集相同。一般改被管理的字符集。 |
5.如果被管理隊(duì)列管理器上的操作用戶與管理隊(duì)列管理器上的操作用戶不同,那么你首先要確認(rèn)管理隊(duì)列管理器上的操作用戶在被管理隊(duì)列管理器上存在并且有管理MQ的權(quán)限,再者,你需要修改服務(wù)器連接通道SYSTEM.ADMIN.SVRCONN的MCAUSER屬性為管理隊(duì)列管理器上的操作用戶。 |
6.啟動(dòng)被管理隊(duì)列管理器上的偵聽器。 |
做完這些工作之后,直接在管理隊(duì)列管理器的MQ管理工具中顯示被管理隊(duì)列管理器即可。然后你就可以象操作本地隊(duì)列管理器一樣,在被管理隊(duì)列管理器上定義你需要的MQ對(duì)象。 |
在配置遠(yuǎn)程連接的時(shí)候,我們?cè)?jīng)創(chuàng)建過進(jìn)程定義。那我們?yōu)槭裁匆?chuàng)建進(jìn)程定義呢?這就涉及MQ通道維護(hù)的概念。 |
通道長(zhǎng)時(shí)間沒有消息觸發(fā)就會(huì)自動(dòng)斷開連接,不再保持運(yùn)行狀態(tài)。時(shí)間的長(zhǎng)短可以由自己設(shè)定,默認(rèn)值為6000秒。消息請(qǐng)求再次來臨的時(shí)候,就必須再次啟動(dòng)通道。有些通道,如服務(wù)器連接通道、接收方通道等是自動(dòng)觸發(fā)啟動(dòng)的。當(dāng)消息請(qǐng)求發(fā)送到通道后,通道立即啟動(dòng),進(jìn)入運(yùn)行狀態(tài)。但也有一些通道不會(huì)自動(dòng)啟動(dòng),最典型的就是發(fā)送方通道。當(dāng)有消息請(qǐng)求需要使用通道進(jìn)行消息傳遞的時(shí)候,發(fā)送方通道也不會(huì)自動(dòng)啟動(dòng)并把消息發(fā)送到遠(yuǎn)程隊(duì)列,而是把消息留在了與其相關(guān)聯(lián)的傳輸隊(duì)列中。 |
但是,在實(shí)際應(yīng)用中我們又不可能每過一段時(shí)間去啟動(dòng)一次通道,或當(dāng)有消息來再去啟動(dòng)通道。那應(yīng)該怎么辦?首先我們創(chuàng)建一個(gè)進(jìn)程定義,這個(gè)進(jìn)程定義的目的就是用來啟動(dòng)發(fā)送方通道。然后我們?cè)趥鬏旉?duì)列的進(jìn)程名稱屬性欄指定剛才定義的進(jìn)程定義名稱,再把觸發(fā)器控制開關(guān)打開。這樣,當(dāng)有消息進(jìn)入傳輸隊(duì)列后,傳輸隊(duì)列的觸發(fā)器會(huì)啟動(dòng)觸發(fā)執(zhí)行指定的進(jìn)程,從而啟動(dòng)發(fā)送方通道,把消息傳輸?shù)竭h(yuǎn)程隊(duì)列中去。 |
也許你會(huì)說你已經(jīng)理解了MQ,包括基本概念、配置、管理以及程序的編寫,那么恭喜你。我也希望如此。不過MQ也許并非如此簡(jiǎn)單,因本人水平有限,也只能到此為止,希望大家再接再厲。順便說一句,如果有什么好想法,千萬別忘了告訴我一聲。 |
|