MQ通訊協議

zrf312發表於2007-10-23

MQ使用TCP/IP,SNA,NETBIOS,DECNET等幾種網路協議,現在通常使用前兩種網路協議,使用後兩種協議的人已經不多了。通訊機制從底層向上是這樣的:
網路層:MQ伺服器執行在指定的IP(如果用TCP/IP協議),LU(SNA協議)或者網路名(NETBIOS,DECNET)上。

資料鏈路層:主要使用TCP資料包,新的MQ版本也有使用UDP資料包的。或者用SNA協議裡的3270資料流。

網路服務層:TCP或UDP資料包被送到預先定義好的MQ網路偵聽服務,如預設的TCP/1414埠上,網路偵聽服務會根據配置啟動相應的通道程式,這些程式不會再協商出動態的新埠,所有連線入這個佇列伺服器的TCP連結都指向這個指定的埠上,連線的另一端(也就是發起連線的一方)由SOCKET呼叫得到一個動態的埠。

應用協議層:MQ的訊息頭與訊息體的資料被MQ軟體以其特有的方式組織成只有MQ認識的資料格式,如果你一定要問協議的名字,在IBM內部被稱為MCP(message channel protocol),但這個名字對使用者基本上沒有什麼意義。新版本的MQ也可以使用HTTPR。

MQ的通訊模式(摘錄)

MQ的通訊模式 1) 點對點通訊:點對點方式是最為傳統和常見的通訊方式,它支援一對一、一對多、多對多、多對一等多種配置方式,支援樹狀、網狀等多種拓撲結構。 2) 多點廣播:MQ適用於不同型別的應用。其中重要的,也是正在發展中的是"多點廣播"應用,即能夠將訊息傳送到多個目標站點(Destination List)。可以使用一條MQ指令將單一訊息傳送到多個目標站點,並確保為每一站點可靠地提供資訊。MQ不僅提供了多點廣播的功能,而且還擁有智慧訊息分發功能,在將一條訊息傳送到同一系統上的多個使用者時,MQ將訊息的一個複製版本和該系統上接收者的名單傳送到目標MQ系統。目標MQ系統在本地複製這些訊息,並將它們傳送到名單上的佇列,從而儘可能減少網路的傳輸量。 3) 釋出/訂閱(Publish/Subscribe)模式:釋出/訂閱功能使訊息的分發可以突破目的佇列地理指向的限制,使訊息按照特定的主題甚至內容進行分發,使用者或應用程式可以根據主題或內容接收到所需要的訊息。釋出/訂閱功能使得傳送者和接收者之間的耦合關係變得更為鬆散,傳送者不必關心接收者的目的地址,而接收者也不必關心訊息的傳送地址,而只是根據訊息的主題進行訊息的收發。在MQ家族產品中,MQ Event Broker是專門用於使用釋出/訂閱技術進行資料通訊的產品,它支援基於佇列和直接基於TCP/IP兩種方式的釋出和訂閱。 4) 群集(Cluster):為了簡化點對點通訊模式中的系統配置,MQ提供Cluster(群集)的解決方案。群集類似於一個域(Domain),群集內部的佇列管理器之間通訊時,不需要兩兩之間建立訊息通道,而是採用群集(Cluster)通道與其它成員通訊,從而大大簡化了系統配置。此外,群集中的佇列管理器之間能夠自動進行負載均衡,當某一佇列管理器出現故障時,其它佇列管理器可以接管它的工作,從而大大提高系統的高可靠性。

MQ的資料(轉載)

一.MQ基本操作 MQ中有幾個很重要的元件:佇列管理器(QueueManager)、佇列(Queue)和通道(Channel)。其基本的操作方法如下: 建立佇列管理器 crtmqm –q QMgrName -q是指建立預設的佇列管理器 刪除佇列管理器 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 建立程式定義 DEFINE PROCESS(PRONAME) + DESCR(‘STRING’)+ APPLTYPE(WINDOWSNT)+ 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 顯示佇列管理器的所有屬性 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下一般情況下在建立佇列管理器時會自動建立偵聽器,啟動佇列管理器時則會自動啟動偵聽程式。當然也可以手動配置偵聽程式。 修改winntsystem32driversetcservices檔案,在檔案中加入一行: MQSeries 1414/tcp #MQSeries channel listener 啟動偵聽程式 runmqlsr –t tcp –p 1414 –m QM_NT 以上說明了怎樣建立簡單的單向傳輸網路。訊息從NT端傳送到UNIX端。建立從UNIX端到NT端的遠端連線和以上相仿,要建立雙向的傳輸網路也是同樣的道理。 三.配置JNDI 用JMS實現訊息的傳送和接收時,經常會用到JNDI。因為JNDI這種方式比較靈活,對於程式設計也比較簡單。 在安裝了MQSeries Client for Java之後,在javabin目錄下找到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。 確認配置檔案之後,可以在javabin目錄下啟動JMSAdmin控制檯。也可以在任何目錄下用下面的命令來啟動控制檯: JMSAdmin –cfg MQ_J***A_INSTALL_PATHjavabinJMSAdmin.config 其中MQ_J***A_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程式設計 上面我們說明了怎樣用JMSAdmin Tool定義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秒。訊息請求再次來臨的時候,就必須再次啟動通道。有些通道,如伺服器連線通道、接收方通道等是自動觸發啟動的。當訊息請求傳送到通道後,通道立即啟動,進入執行狀態。但也有一些通道不會自動啟動,最典型的就是傳送方通道。當有訊息請求需要使用通道進行訊息傳遞的時候,傳送方通道也不會自動啟動並把訊息傳送到遠端佇列,而是把訊息留在了與其相關聯的傳輸佇列中。 但是,在實際應用中我們又不可能每過一段時間去啟動一次通道,或當有訊息來再去啟動通道。那應該怎麼辦?首先我們建立一個程式定義,這個程式定義的目的就是用來啟動傳送方通道。然後我們在傳輸佇列的程式名稱屬性欄指定剛才定義的程式定義名稱,再把觸發器控制開關開啟。這樣,當有訊息進入傳輸佇列後,傳輸佇列的觸發器會啟動觸發執行指定的程式,從而啟動傳送方通道,把訊息傳輸到遠端佇列中去。

[@more@]MQ通訊模式

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/477222/viewspace-978138/,如需轉載,請註明出處,否則將追究法律責任。

相關文章