摘自:http://blog.sina.com.cn/s/blog_4892cf780100erga.htmlhtml
一.MQ基本操做java
MQ中有幾個很重要的組件:隊列管理器(QueueManager)、隊列(Queue)和通道(Channel)。其基本的操做方法以下:web
#建立隊列管理器 #-q是指建立缺省的隊列管理器 crtmqm –q QMgrName #刪除隊列管理器 dltmqm QmgrName #啓動隊列管理器 #若是是啓動默認的隊列管理器,能夠不帶其名字 strmqm QmgrName #中止隊列管理器 endmqm QmgrName #受控中止 endmqm –i QmgrName #當即中止 endmqm –p QmgrName #強制中止 #顯示隊列管理器 dspmq –m QmgrName #運行MQSeries命令 #若是是默認隊列管理器,能夠不帶其名字 runmqsc QmgrName #往隊列中放消息 #若是隊列是默認隊列管理器中的隊列,能夠不帶其隊列管理器的名字 amqsput QName QmgrName #從隊列中取出消息 #若是隊列是默認隊列管理器中的隊列,能夠不帶其隊列管理器的名字 amqsget QName QmgrName #啓動通道 runmqchl –c ChlName –m QmgrName #啓動偵聽 runmqlsr –t TYPE –p PORT –m QMgrName #中止偵聽 endmqlsr -m QmgrName MQSeries命令 #定義死信隊列 DEFINE QLOCAL(QNAME) DEFPSIST(YES) REPLACE #設定隊列管理器的死信隊列 ALTER QMGR DEADQ(QNAME) #定義本地隊列 DEFINE QL(QNAME) REPLACE #定義別名隊列 DEFINE QALIAS(QALIASNAME) TARGQ(QNAME) #遠程隊列定義
#這裏的+號是續行符,注意+號後有個空格存在 DEFINE QREMOTE(QRNAME) + RNAME(AAA) RQMNAME(QMGRNAME) + XMITQ(QTNAME) #定義模型隊列 DEFINE QMODEL(QNAME) DEFTYPE(TEMPDYN) #定義本地傳輸隊列 DEFINE QLOCAL(QTNAME) USAGE(XMITQ) DEFPSIST(YES) + INITQ(SYSTEM.CHANNEL.INITQ) + PROCESS(PROCESSNAME) REPLACE #建立進程定義 #其中APPLTYPE的值能夠是:CICS、UNIX、WINDOWS、WINDOWSNT等 DEFINE PROCESS(PRONAME) + DESCR('STRING') + APPLTYPE(WINDOWSNT) + APPLICID('runmqchl -c SDR_TEST -m QM_ TEST') #建立發送方通道 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 #顯示隊列管理器的全部屬性 DISPLAY QMGR [ALL] #顯示進程定義 DISPLAY PROCESS(PRONAME) #更改屬性 ALTER QMGR DESCR('NEW DESCRIPTION') ALTER QLOCAL(QNAME) PUT(DISABLED) ALTER QALIAS(QNAME) TARGQ(TARGQNAME) #刪除隊列 DELETE QLOCAL(QNAME) DELETE QREMOTE(QRNAME) #清除隊列中的全部消息 CLEAR QLOCAL(QNAME)
二.配置一個可以通訊的遠程鏈接編程
以上講述了MQ的基本命令操做,但只知道這些是沒有實際意義的。MQ的最終目的是實現遠程通訊,因此下面就以一個具體的例子來講明如何實現遠程鏈接。這個例子的目的是創建能夠實現消息傳遞的一對MQ服務器,它們分別基於NT和UNIX平臺。安全
#首先在NT端建一隊列管理器 crtmqm –q QM_NT #啓動隊列管理器 strmqm QM_NT #運行MQ控制檯命令 runmqsc QM_NT #建立死信隊列 DEFINE QL(NT.DEADQ) DEFPSIST(YES) REPLACE #更改隊列管理器屬性,設置其死信隊列 ALTER QMGR DEADQ(NT.DEADQ) #建立進程定義 DEFINE PROCESS(P_NT) + APPLTYPE(WINDOWSNT) + APPLICID('runmqchl -c SDR_NT -m QM_NT') #建立本地傳輸隊列 DEFINE QL(QT_NT) USAGE(XMITQ) DEFPSIST(YES) + INITQ(SYSTEM.CHANNEL.INITQ) + PROCESS(P_NT) REPLACE #建立遠程隊列定義,對應於UNIX機器上的本地隊列Q_UNIX,傳輸隊列爲QT_NT DEFINE QREMOTE(QR_NT) + RNAME(Q_UNIX) RQMNAME(QM_UNIX) + XMITQ(QT_NT) #建立發送方通道,其傳輸隊列爲QT_NT,遠程主機地址爲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端建立隊列管理器 crtmqm –q QM_UNIX #啓動隊列管理器 strmqm QM_UNIX #添加偵聽程序 #修改/etc/services文件,加入一行: MQSeries 1414/tcp #MQSeries channel listener #修改/etc/inetd.conf文件,加入一行(啓動偵聽程序) MQSeries stream tcp nowait mqm /usr/lpp/mqm/bin/amqcrsta amqcrsta –m QM_UNIX #運行如下命令,以使修改起做用 refresh –s inetd #運行MQ控制檯命令 runmqsc QM_UNIX #建立死信隊列 DEFINE QL(UNIX.DEADQ) DEFPSIST(YES) REPLACE #更改隊列管理器屬性,設置其死信隊列 ALTER QMGR DEADQ(UNIX.DEADQ) #建立接收方通道,其名字必須與遠程發送方相同 DEFINE CHANNEL(SDR_NT) CHLTYPE(RCVR) REPLACE #建立本地隊列 DEFINE QL(Q_UNIX) DEFPSIST(YES) REPLACE #建立服務器鏈接通道 DEFINE CHANNEL(S_UNIX) CHLTYPE(SVRCONN) REPLACE #通過以上操做以後,遠程鏈接的配置工做完成。接下來須要驗證配置是否正確。 #在NT端啓動發送方通道 runmqchl –c SDR_NT –m QM_NT 或 start chl(SDR_NT) #從NT端發送消息到UNIX端 amqsput QR_NT QM_NT #在UNIX端接收消息 /usr/mqm/samp/bin/amqsget Q_UNIX QM_UNIX #若能收到消息,說明配置成功。 #另,在NT下通常狀況下在創建隊列管理器時會自動創建偵聽器,啓動隊列管理器時則會自動啓動偵聽程序。固然也能夠手動配置偵聽程序。 #修改\winnt\system32\drivers\etc\services文件,在文件中加入一行: MQSeries 1414/tcp #MQSeries channel listener #啓動偵聽程序 runmqlsr –t tcp –p 1414 –m QM_NT
以上說明了怎樣創建簡單的單向傳輸網絡。消息從NT端傳送到UNIX端。創建從UNIX端到NT端的遠程鏈接和以上相仿,要創建雙向的傳輸網絡也是一樣的道理。服務器
三.配置JNDI網絡
用JMS實現消息的發送和接收時,常常會用到JNDI。由於JNDI這種方式比較靈活,對於編程也比較簡單。tcp
#在安裝了MQSeries Client for Java以後,在\java\bin目錄下找到JMSAdmin.config文件。
#該文件主要用來講明Context的存儲方式及存儲地址,對應於文件中的兩個參數INITIAL_CONTEXT_FACTORY和PROVIDER_URL。
#典型的JMSAdmin.config文件內容以下: #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使用的服務提供商。當前有三種受支持的值:
# com.sun.jndi.ldap.LdapCtxFactory用於 LDAP,若是使用它就必須安裝一個LDAP服務器。
# com.sun.jndi.fscontext.RefFSContextFactory用於文件系統上下文,它只須要使用者提供存放上下文的文件路徑。
# com.ibm.ejs.ns.jndi.CNInitialContextFactory是專門爲 websphere提供的,它須要和websphere的CosNaming資源庫一塊兒使用。 #PROVIDER_URL表示會話初始上下文的URL,由JMSAdmin #tool實現的全部JNDI操做的根。它和INITIAL_CONTEXT_FACTORY一一對應。 ldap://hostname/contextname 用於LDAP file:[drive:]/pathname 用於文件系統上下文 iiop://hostname[:port]/[?TargetContext=ctx] 用於訪問websphere CosNaming名稱空間 #最後還有一個參數SECURITY_AUTHENTICATION,用於說明JNDI是否把安全性憑證傳遞給了您使用的服務供應商。
#只有當使用了LDAP服務供應商時,才使用此參數。此參數有三個值,none(匿名認證)、simple(簡單認證)和CRAM-MD5認證機制。
#若是沒有提供有效值,缺省值爲none。 #確認配置文件以後,能夠在\java\bin目錄下啓動JMSAdmin控制檯。也能夠在任何目錄下用下面的命令來啓動控制檯: JMSAdmin –cfg MQ_JAVA_INSTALL_PATH\java\bin\JMSAdmin.config #其中MQ_JAVA_INSTALL_PATH爲MQSeries Client for Java安裝的根目錄。 #若啓動失敗,則好好檢查一下您的環境變量是否設置正確。
#根據我我的的經驗,除了把com.ibm.mq.jar和com.ibm.mqjms.jar加入到環境變量外,還要把fscontext.jar和providerutil.jar加入到環境變量。 #進入JMSAdmin控制檯後,您能夠自由定義sub context。對於子上下文的操做,主要有一下命令: display ctx define ctx(ctxname) change ctx(ctxname) change ctx(=up) change ctx(=init) delete ctx(ctxname) #固然,在這裏的主要任務並不是是用來定義sub context,而是用來定義如下幾個對象: MQQueueConnectionFactory MQTopicConnectionFactory MQQueue MQTopic #(還有其它的一些對象,如MQXAQueueConnectionFactory等,不經常使用到,在此不做說明。) #可使用不少動詞來操縱目錄名稱空間中的受管理對象。
#ALTER、DEFINE、DISPLAY、DELETE、COPY和MOVE,它們的用法都算比較簡單,這裏只列舉一二以做說明。 #例一:定義一QueueConnectionFactory,鏈接主機10.10.10.18,端口1414 DEFINE QCF(EXAMPLEQCF)+ DESC(Example Queue Connection Factory) + TRAN(CLIENT) + HOST(10.10.10.18) + QMGR(QM_EXAMPLE) + CHAN(S_EXAMPLE) + PORT(1414) + CCSID(1381) #例二:定義一Queue,其對應於MQ中的Q_EXAMPLE DEFINE Q(EXAMPLEQL) + DESC(Local queue) + QMGR(QM_EXAMPLE) + QUEUE(Q_EXAMPLE) + CCSID(1381)
四.用JMS實現MQ編程ide
上面咱們說明了怎樣用JMSAdminTool定義MQ對象的上下文。工具
咱們的最終目的是要用JMS來實現MQ編程,以實如今程序中對MQ隊列進行收、發消息。因此,下面咱們將重點討論一下MQ的JMS實現。
若是您對JMS編程很熟悉,那麼您也就會用JMS來實現MQ編程,由於用JMS來編寫MQ程序與編寫通常的JMS程序沒有太大的差異。舉個例子,當咱們想發送一條消息到MQ的隊列中,再從該隊列中取回消息時,咱們編程時主要有四個步驟。首先咱們要初始化在程序中要用到的對象,而後才能夠發送消息到隊列中去,再就是收取消息了,最後要清除那些永久對象。這些都和普通的JMS程序至關。程序的源代碼以下:
import java.util.Hashtable; import javax.jms.*; import javax.naming.*; import javax.naming.directory.*; public class sample { 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); Queue q1=null; 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); connection.start(); } 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 { queueSession.close(); connection.close(); } public static void main(String[] args){ String rec; sample sp = new sample(); try { sp.sampleInit(); sp.sendMessageOut("Hello World!"); java.lang.Thread.sleep(4000); rec=sp.receiveMessage(); System.out.println("Receive text is : "+rec); sp.sampleClose(); }catch(Exception e) { e.printStackTrace(); } } }
五.遠程管理
MQ在WINDOWS平臺下具備圖形化管理界面,但在UNIX平臺下卻只能經過命令行來進行操做。這樣就給使用者帶來很大的不便。咱們都但願能經過圖形界面來進行管理配置。爲了實現咱們的想法,咱們就必須創建遠程管理。
實現遠程管理有如下幾個步驟:
1.被管理隊列管理器上的命令隊列SYSTEM.ADMIN.COMMAND.QUEUE存在並可用。對於MQ 2版本應執行amqscoma.tst 腳原本建立。 2.使用strmqcsv命令來啓動被管理隊列管理器上的命令服務器。 3.肯定被管理隊列管理器上的服務器鏈接通道SYSTEM.ADMIN.SVRCONN是否存在,若是不存在則建立它。 4.通常Unix、Linux平臺中MQ默認的字符集爲819,而Windows平臺爲1381,因此你必須改變其字符集,使兩邊的字符集相同。通常改被管理的字符集。 5.若是被管理隊列管理器上的操做用戶與管理隊列管理器上的操做用戶不一樣,那麼你首先要確認管理隊列管理器上的操做用戶在被管理隊列管理器上存在而且有管理MQ的權限. 再者,你須要修改服務器鏈接通道SYSTEM.ADMIN.SVRCONN的MCAUSER屬性爲管理隊列管理器上的操做用戶。 6.啓動被管理隊列管理器上的偵聽器。
作完這些工做以後,直接在管理隊列管理器的MQ管理工具中顯示被管理隊列管理器便可。而後你就能夠象操做本地隊列管理器同樣,在被管理隊列管理器上定義你須要的MQ對象。
六.通道維護
在配置遠程鏈接的時候,咱們曾經建立過進程定義。那咱們爲何要去建立進程定義呢?這就涉及MQ通道維護的概念。 通道長時間沒有消息觸發就會自動斷開鏈接,再也不保持運行狀態。時間的長短能夠由本身設定,默認值爲6000秒。消息請求再次來臨的時候,就必須再次啓動通道。有些通道,如服務器鏈接通道、接收方通道等是自動觸發啓動的。當消息請求發送到通道後,通道當即啓動,進入運行狀態。但也有一些通道不會自動啓動,最典型的就是發送方通道。當有消息請求須要使用通道進行消息傳遞的時候,發送方通道也不會自動啓動並把消息發送到遠程隊列,而是把消息留在了與其相關聯的傳輸隊列中。 可是,在實際應用中咱們又不可能每過一段時間去啓動一次通道,或當有消息來再去啓動通道。那應該怎麼辦?首先咱們建立一個進程定義,這個進程定義的目的就是用來啓動發送方通道。而後咱們在傳輸隊列的進程名稱屬性欄指定剛纔定義的進程定義名稱,再把觸發器控制開關打開。這樣,當有消息進入傳輸隊列後,傳輸隊列的觸發器會啓動觸發執行指定的進程,從而啓動發送方通道,把消息傳輸到遠程隊列中去。