消息队列MQ技术的原理和IBM MQ的基本操作

消息队列技术是分布式应用间交换信息的一种技术。消息队列可驻留在内存或磁盘上,队列存储消息直到它们被应用程序读走。通过消息队列,应用程序可独立地执行--它们不需要知道彼此的位置、或在继续执行前不需要等待接收程序接收此消息。

消息中间件概述

消息队列技术是分布式应用间交换信息的一种技术。消息队列可驻留在内存或磁盘上,队列存储消息直到它们被应用程序读走。通过消息队列,应用程序可独立地执行--它们不需要知道彼此的位置、或在继续执行前不需要等待接收程序接收此消息。

在分布式计算环境中,为了集成分布式应用,开发者需要对异构网络环境下的分布式应用提供有效的通信手段。为了管理需要共享的信息,对应用提供公共的信息交换机制是重要的。

设计分布式应用的方法主要有:远程过程调用(PRC)--分布式计算环境(DCE)的基础标准成分之一;对象事务监控(OTM)--基于CORBA的面向对象工业标准与事务处理(TP)监控技术的组合;消息队列(MessageQueue)--构造分布式应用的松耦合方法。

(a) 分布计算环境/远程过程调用 (DCE/RPC)

RPC是DCE的成分,是一个由开放软件基金会(OSF)发布的应用集成的软件标准。RPC模仿一个程序用函数引用来引用另一程序的传统程序设计方法,此引用是过程调用的形式,一旦被调用,程序的控制则转向被调用程序。

在RPC实现时,被调用过程可在本地或远地的另一系统中驻留并在执行。当被调用程序完成处理输入数据,结果放在过程调用的返回变量中返回到调用程序。RPC完成后程序控制则立即返回到调用程序。因此RPC模仿子程序的调用/返回结构,它仅提供了Client(调用程序)和Server(被调用过程)间的同步数据交换。

(b) 对象事务监控 (OTM)

基于CORBA的面向对象工业标准与事务处理(TP)监控技术的组合,在CORBA规范中定义了:使用面向对象技术和方法的体系结构;公共的Client/Server程序设计接口;多平台间传输和翻译数据的指导方针;开发分布式应用接口的语言(IDL)等,并为构造分布的Client/Server应用提供了广泛及一致的模式。

(c) 消息队列 (Message Queue)

消息队列为构造以同步或异步方式实现的分布式应用提供了松耦合方法。消息队列的API调用被嵌入到新的或现存的应用中,通过消息发送到内存或基于磁盘的队列或从它读出而提供信息交换。消息队列可用在应用中以执行多种功能,比如要求服务、交换信息或异步处理等。

中间件是一种独立的系统软件或服务程序,分布式应用系统借助这种软件在不同的技术之间共享资源,管理计算资源和网络通讯。它在计算机系统中是一个关键软件,它能实现应用的互连和互操作性,能保证系统的安全、可靠、高效的运行。中间件位于用户应用和操作系统及网络软件之间,它为应用提供了公用的通信手段,并且独立于网络和操作系统。中间件为开发者提供了公用于所有环境的应用程序接口,当应用程序中嵌入其函数调用,它便可利用其运行的特定操作系统和网络环境的功能,为应用执行通信功能。

如果没有消息中间件完成信息交换,应用开发者为了传输数据,必须要学会如何用网络和操作系统软件的功能,编写相应的应用程序来发送和接收信息,且交换信息没有标准方法,每个应用必须进行特定的编程从而和多平台、不同环境下的一个或多个应用通信。例如,为了实现网络上不同主机系统间的通信,将要求具备在网络上如何交换信息的知识(比如用TCP/IP的socket程序设计);为了实现同一主机内不同进程之间的通讯,将要求具备操作系统的消息队列或命名管道(Pipes)等知识。

目前中间件的种类很多,如交易管理中间件(如IBM的CICS)、面向Java应用的Web应用服务器中间件(如IBM的WebSphere Application Server)等,而消息传输中间件(MOM)是其中的一种。它简化了应用之间数据的传输,屏蔽底层异构操作系统和网络平台,提供一致的通讯标准和应用开发,确保分布式计算网络环境下可靠的、跨平台的信息传输和数据交换。它基于消息队列的存储-转发机制,并提供特有的异步传输机制,能够基于消息传输和异步事务处理实现应用整合与数据交换。

IBM 消息中间件MQ以其独特的安全机制、简便快速的编程风格、卓越不凡的稳定性、可扩展性和跨平台性,以及强大的事务处理能力和消息通讯能力,成为业界市场占有率最高的消息中间件产品。

MQ具有强大的跨平台性,它支持的平台数多达35种。它支持各种主流Unix操作系统平台,如:HP-UX、AIX、SUN Solaris、Digital UNIX、Open VMX、SUNOS、NCR UNIX;支持各种主机平台,如:OS/390、MVS/ESA、VSE/ESA;同样支持Windows NT服务器。在PC平台上支持Windows9X/Windows NT/Windows 2000和UNIX (UnixWare、Solaris)以及主要的Linux版本(Redhat、TurboLinux等)。此外,MQ还支持其他各种操作系统平台,如:OS/2、AS/400、Sequent DYNIX、SCO OpenServer、SCO UnixWare、Tandem等。

 

MQ的基本概念:

1) 队列管理器

队列管理器是MQ系统中最上层的一个概念,由它为我们提供基于队列的消息服务。

2) 消息

在MQ中,我们把应用程序交由MQ传输的数据定义为消息,我们可以定义消息的内容并对消息进行广义的理解,比如:用户的各种类型的数据文件,某个应用向其它应用发出的处理请求等都可以作为消息。消息有两部分组成:

消息描述符(Message Discription或Message Header),描述消息的特征,如:消息的优先级、生命周期、消息Id等;

消息体(Message Body),即用户数据部分。在MQ中,消息分为两种类型,非永久性(non-persistent)消息和永久性(persistent)消息,非永久性消息是存储在内存中的,它是为了提高性能而设计的,当系统掉电或MQ队列管理器重新启动时,将不可恢复。当用户对消息的可靠性要求不高,而侧重系统的性能表现时,可以采用该种类型的消息,如:当发布股票信息时,由于股票信息是不断更新的,我们可能每若干秒就会发布一次,新的消息会不断覆盖旧的消息。永久性消息是存储在硬盘上,并且纪录数据日志的,它具有高可靠性,在网络和系统发生故障等情况下都能确保消息不丢、不重。

此外,在MQ中,还有逻辑消息和物理消息的概念。利用逻辑消息和物理消息,我们可以将大消息进行分段处理,也可以将若干个本身完整的消息在应用逻辑上归为一组进行处理。

 

3) 队列

队列是消息的安全存放地,队列存储消息直到它被应用程序处理。

消息队列以下述方式工作:

a) 程序A形成对消息队列系统的调用,此调用告知消息队列系统,消息准备好了投向程序B;

b) 消息队列系统发送此消息到程序B驻留处的系统,并将它放到程序B的队列中;

c) 适当时间后,程序B从它的队列中读此消息,并处理此信息。

 

由于采用了先进的程序设计思想以及内部工作机制,MQ能够在各种网络条件下保证消息的可靠传递,可以克服网络线路质量差或不稳定的现状,在传输过程中,如果通信线路出现故障或远端的主机发生故障,本地的应用程序都不会受到影响,可以继续发送数据,而无需等待网络故障恢复或远端主机正常后再重新运行。

在MQ中,队列分为很多种类型,其中包括:本地队列、远程队列、模板队列、动态队列、别名队列等。

本地队列又分为普通本地队列和传输队列,普通本地队列是应用程序通过API对其进行读写操作的队列;传输队列可以理解为存储-转发队列,比如:我们将某个消息交给MQ系统发送到远程主机,而此时网络发生故障,MQ将把消息放在传输队列中暂存,当网络恢复时,再发往远端目的地。

远程队列是目的队列在本地的定义,它类似一个地址指针,指向远程主机上的某个目的队列,它仅仅是个定义,不真正占用磁盘存储空间。

模板队列和动态队列是MQ的一个特色,它的一个典型用途是用作系统的可扩展性考虑。我们可以创建一个模板队列,当今后需要新增队列时,每打开一个模板队列,MQ便会自动生成一个动态队列,我们还可以指定该动态队列为临时队列或者是永久队列,若为临时队列我们可以在关闭它的同时将它删除,相反,若为永久队列,我们可以将它永久保留,为我所用。

4) 通道

通道是MQ系统中队列管理器之间传递消息的管道,它是建立在物理的网络连接之上的一个逻辑概念,也是MQ产品的精华。

在MQ中,主要有三大类通道类型,即消息通道,MQI通道和Cluster通道。消息通道是用于在MQ的服务器和服务器之间传输消息的,需要强调指出的是,该通道是单向的,它又有发送(sender), 接收(receive), 请求者(requestor), 服务者(server)等不同类型,供用户在不同情况下使用。MQI通道是MQ Client和MQI通道是MQ Client和MQ Server之间通讯和传输消息用的,与消息通道不同,它的传输是双向的。群集(Cluster)通道是位于同一个MQ 群集内部的队列管理器之间通讯使用的。

 


首先来看本地通讯的情况,应用程序A和应用程序B运行于同一系统A,它们之间可以借助消息队列技术进行彼此的通讯:应用程序A向队列1发送一条信息,而当应用程序B需要时就可以得到该信息。
其次是远程通讯的情况,如果信息传输的目标改为在系统B上的应用程序C,这种变化不会对应用程序A产生影响,应用程序A向队列2发送一条信息,系统A的MQ发现Q2所指向的目的队列实际上位于系统B,它将信息放到本地的一个特殊队列-传输队列(Transmission Queue)。我们建立一条从系统A到系统B的消息通道,消息通道代理将从传输队列中读取消息,并传递这条信息到系统B,然后等待确认。只有MQ接到系统B成功收到信息的确认之后,它才从传输队列中真正将该信息删除。如果通讯线路不通,或系统B不在运行,信息会留在传输队列中,直到被成功地传送到目的地。这是MQ最基本而最重要的技术--确保信息传输,并且是一次且仅一次(once-and-only-once)的传递。
MQ提供了用于应用集成的松耦合的连接方法,因为共享信息的应用不需要知道彼此物理位置(网络地址);不需要知道彼此间怎样建立通信;不需要同时处于运行状态;不需要在同样的操作系统或网络环境下运行。

MQ的基本配置举例
在上图中,要实现网络上两台主机上的通讯,若采用点对点的通讯方式,我们至少要建立如下MQ的对象:
在发送方A:
1) 建立队列管理器QMA: crtmqm -q QMA
2) 定义本地传输队列: define qlocal (QMB) usage (xmitq) defpsist(yes)
3) 创建远程队列: define qremote (QR.TOB) rname (LQB) rqmname (QMB) xmitq (QMB)
4) 定义发送通道: define channel (A.TO.B) chltype (sdr) conname ('IP of B') xmitq (QMB) + trptype (tcp)

在接收方B:
1) 建立队列管理器QMB: crtmqm -q QMB
2) 定义本地队列QLB: define qlocal (LQB)
3) 创建接收通道: define channel (A.TO.B) chltype (rcvr) trptype (tcp)
经过上述配置,我们就可以实现从主机A到B的单向通讯,若要实现二者之间的双向通讯,可参考此例创建所需要的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)。其基本的操作方法如下:
   
1)创建队列管理器 
crtmqm –q QMgrName 
-q是指创建缺省的队列管理器 
  
2)删除队列管理器 
dltmqm QmgrName
  3)启动队列管理器 
strmqm QmgrName 
如果是启动默认的队列管理器,可以不带其名字
  4)停止队列管理器 
endmqm QmgrName 受控停止 
endmqm –i QmgrName 立即停止 
endmqm –p QmgrName 强制停止
  5)显示队列管理器 
dspmq –m QmgrName
  6)运行MQSeries命令 
runmqsc QmgrName 
如果是默认队列管理器,可以不带其名字
  7)往队列中放消息 
amqsput QName QmgrName 
如果队列是默认队列管理器中的队列,可以不带其队列管理器的名字
  8)从队列中取出消息 
amqsget QName QmgrName 
如果队列是默认队列管理器中的队列,可以不带其队列管理器的名字
  9)启动通道 
runmqchl –c ChlName –m QmgrName 
例:runmqchl -c CLNT_CHAN_PUMA -m JTXWBP01
  10)启动侦听 
runmqlsr –t TYPE –p PORT –m QMgrName 
例:runmqlsr -t TCP -p 1414 -m JTXWBP01
  11)停止侦听 
endmqlsr -m QmgrName
  MQSeries命令 
1)定义死信队列 
DEFINE QLOCAL(QNAME) DEFPSIST(YES) REPLACE
  2)设定队列管理器的死信队列 
ALTER QMGR DEADQ(QNAME)
  3)定义本地队列 
DEFINE QL(QNAME) REPLACE
  4)定义别名队列 
DEFINE QALIAS(QALIASNAME) TARGQ(QNAME)
  5)远程队列定义 
DEFINE QREMOTE(QRNAME) + 
RNAME(AAA) RQMNAME(QMGRNAME) + 
XMITQ(QTNAME)
  6)定义模型队列 
DEFINE QMODEL(QNAME) DEFTYPE(TEMPDYN)
  7)定义本地传输队列 
DEFINE QLOCAL(QTNAME) USAGE(XMITQ) DEFPSIST(YES) + 
INITQ(SYSTEM.CHANNEL.INITQ)+ 
PROCESS(PROCESSNAME) REPLACE
  8)创建进程定义 
DEFINE PROCESS(PRONAME) + 
DESCR(‘STRING’)+ 
APPLTYPE(WINDOWSNT)+ 
APPLICID(’ runmqchl -c SDR_TEST -m QM_ TEST’) 
  其中APPLTYPE的值可以是:CICS、UNIX、WINDOWS、WINDOWSNT等
  9)创建发送方通道 
  DEFINE CHANNEL(SDRNAME) CHLTYPE(SDR)+ 
CONNAME(‘100.100.100.215(1418)’) XMITQ(QTNAME) REPLACE 
其中CHLTYPE可以是:SDR、SVR、RCVR、RQSTR、CLNTCONN、SVRCONN、CLUSSDR和CLUSRCVR。
  10)创建接收方通道 
DEFINE CHANNEL(SDR_ TEST) CHLTYPE(RCVR) REPLACE
  11)创建服务器连接通道 
DEFINE CHANNEL(SVRCONNNAME) CHLTYPE(SVRCONN) REPLACE
  12)显示队列的所有属性 
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端建一队列管理器 
1)crtmqm –q QM_NT  crtmqm –q JTXWBP01

  2)启动队列管理器 
strmqm QM_NT   strmqm

  3)运行MQ控制台命令  
  runmqsc QM_NT runmqsc

4)创建送信队列 
DEFINE QL(NT.DEADQ) DEFPSIST(YES) REPLACE   DEFINE QL(RQ_PUMA_REQUEST) DEFPSIST(YES) REPLACE   

5)更改队列管理器属性,设置其送信队列 
ALTER QMGR DEADQ(NT.DEADQ) ALTER QMGR DEADQ(RQ_PUMA_REQUEST) 

6)创建进程定义 
DEFINE PROCESS(P_NT)+ 
APPLTYPE(WINDOWSNT)+ 
APPLICID(’ runmqchl -c SDR_NT -m QM_NT’) 
DEFINE PROCESS(P_NT) APPLTYPE(WINDOWSNT) APPLICID(‘runmqchl -c CLNT_CHAN_PUMA -m JTXWBP01‘)
  7)创建本地传输队列 
DEFINE QL(QT_NT) USAGE(XMITQ) DEFPSIST(YES) + 
INITQ(SYSTEM.CHANNEL.INITQ)+ 
PROCESS(P_NT) REPLACE 
  DEFINE QL(LQ_PUMA_REPLY) USAGE(XMITQ) DEFPSIST(YES) INITQ(SYSTEM.CHANNEL.INITQ) PROCESS(P_NT) REPLACE
  8)创建远程队列定义,对应于UNIX机器上的本地队列Q_UNIX,传输队列为QT_NT 
DEFINE QREMOTE(QR_NT)+ 
RNAME(Q_UNIX) RQMNAME(QM_UNIX)+ 
XMITQ(QT_NT) 
DEFINE QREMOTE(LQ_PUMA_REPLY) RQMNAME(JTXWBP01) XMITQ(RQ_PUMA_REQUEST)
  9)创建发送方通道,其传输队列为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(CLNT_CHAN_PUMA) CHLTYPE(SDR) CONNAME(‘10.4.2.241(1414)‘) XMITQ(RQ_PUMA_REQUEST) REPLACE 
  10)创建服务器连接通道 
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这种方式比较灵活,对于编程也比较简单。 
在安装了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编程 
上面我们说明了怎样用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秒。
消息请求再次来临的时候,就必须再次启动通道。有些通道,如服务器连接通道、接收方通道等是自动触发启动的。
当消息请求发送到通道后,通道立即启动,进入运行状态。但也有一些通道不会自动启动,最典型的就是发送方通道。
当有消息请求需要使用通道进行消息传递的时候,发送方通道也不会自动启动并把消息发送到远程队列,
而是把消息留在了与其相关联的传输队列中。 
但是,在实际应用中我们又不可能每过一段时间去启动一次通道,或当有消息来再去启动通道。
那应该怎么办?首先我们创建一个进程定义,这个进程定义的目的就是用来启动发送方通道。
然后我们在传输队列的进程名称属性栏指定刚才定义的进程定义名称,再把触发器控制开关打开。
这样,当有消息进入传输队列后,传输队列的触发器会启动触发执行指定的进程,
从而启动发送方通道,把消息传输到远程队列中去。 
显示通道状态:
dis chstatus(*)
SUSPEND QMGR CLUSTER(SALES)
设置队列管理器的自启动
amqmdain

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值