MQ学习

来源:互联网 发布:淘宝贷款15万 交3000 编辑:程序博客网 时间:2024/06/13 11:42

转载自:http://blog.sina.com.cn/s/blog_62339a24010162tz.html

消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过写和检索出入列队的针对应用程序的数据(消息)来通信,而无需专用连接来链接它们。消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。

IBM WebSphere MQ 产品支持应用程序通过不同组件如处理器、子系统、操作系统以及通信协议的网络彼此进行通信。例如,IBM WebSphere MQ 支持 35 种以上的不同操作系统。

IBM WebSphere MQ 支持两种不同的应用程序编程接口:Java 消息服务(JMS)和消息队列接口(MQI)。在 IBM WebSphere MQ 服务器上,JMS 绑定方式被映射到 MQI。如图 3 所示,应用程序直接与其本地队列管理器通过使用 MQI 进行对话,MQI 是一组要求队列管理器提供服务的调用。MQI 的引人之处是它只提供 13 次调用。这意味着对于应用程序编程员它是一种非常易于使用的接口,因为大部分艰苦工作都将透明完成的。

图形 2. IBM WebSphere MQ 编程


按此在新窗口浏览图片
图 2 显示了 IBM WebSphere MQ 编程的原理。第一步是让应用程序与队列管理器连接。它通过 MQConnect 调用来进行此连接。下一步使用 MQOpen 调用为输出打开一个队列。然后应用程序使用 MQPut 调用将其数据放到队列上。要接收数据,应用程序调用 MQOpen 调用打开输入队列。应用程序使用 MQGet 调用从队列上接收数据。

图 中还显示了消息通道代理(MCA)、通道出口和对象权限管理器(OAM)。MCA 是 IBM WebSphere MQ 程序,它使用现有传输服务诸如 TCP/IP 与 SNA 将消息从本地传输队列移到目标队列管理器。这些传输服务即通道。通道出口是用户写入库,可以在通道运作期间,从已定义位置号之一进入这些库。OAM 是命令和对象管理的缺省授权服务(针对操作系统)。这三个组件对 IBM WebSphere MQ 的现有安全性解决方案非常重要。

MQ 介绍及安装

介绍

MQ,简单地说就是消息队列,应用程序把消息放进队列里,等待其他的应用程序或自己把它读走,用于进程间通信,并且可以像 socket 那样用于不同主机间的进程间通信。它有四个重要的概念:

队列管理器
用来管理队列。

队列
用来存放消息。

消息
就是要进行存储与传递的消息。

通道
队列管理器之间传递消息的管道。

安装

到这里下载 MQ for 64-bit linux。下载完解压后,先运行 MQ 的许可证程序:

./mqlisence.sh  

然后安装你想要装的组件:

rpm -U MQSeriesXXXXXXX.rpm  

MQ 基本操作

创建队列管理器

crtmqm -q qm_name  

启动队列管理器

strmqm qm_name  

查看队列管理器

dspmq -m qm_name  

创建队列
创建队列不像创建队列管理器那样有直接的命令可以使用,而是要先运行命令:

runmqsc  

再执行语句:

def ql(QUEUE1)  

也可以把语句写到一个文件里面,再把这个文件当作 runmqsc 的输入:

runmqsc < statement.txt  

如果在执行 strmqm qm_name 之后再运行 runmqsc,就表示是对 qm_name 这个队列管理器进行操作,如果要想对其他的队列管理器操作,则要在runmqsc 后面加队列管理器名:

runmqsc qm_name  

队列有很多属性,具体的细节可查看 IBM 的手册。

停止队列管理器

endmqm qm_name // 受控停止 endmqm -i qm_name // 立即停止 endmqm -p qm_name // 强制停止  

删除队列管理器

dltmqm qm_name  

错误与及解决办法
我在创建队列管理器时出现下以提示信息:

The queue manager is associated with installation ‘Installation1’. AMQ6024: Insufficient resources are available to complete a system request.

错误信息在 /var/mqm/errors/ 可以查看到:

cat AMQ7116.0.FDC  

Probe Description :- AMQ6024: Insufficient resources are available to
complete a system request.
FDCSequenceNumber :- 0
Arith1 :- 18446744073709551615 (0xffffffffffffffff)
Arith2 :- 22 (0x16)
Comment1 :- Failed to get memory segment: shmget(0x00000000,
73834496) [rc=-1 errno=22] Invalid argument
Comment2 :- Invalid argument
Comment3 :- Configure kernel (for example, shmmax) to allow a
shared memory segment of at least 73834496 bytes

这个问题可以这样解决:

sudo sysctl -w kernel.shmmax=73834496  

sysctl 可以动态修改内核参数而不用重启。

MQ client 封装库

MQI

Message Queue Interface 一共包含 13 个函数。它们分别是(可以在 cmqc.h 查看它们的原型):
MQCONN 和 MQCONNX
连接队列管理器。两者唯一的区别是 MQCONNX 比 MQCONN 多了一个连接选项参数。

MQDISC
断开与队列管理器的连接。

MQOPEN 和 MQCLOSE
每一个队列都必须单独调用 MQOPEN 来打开。并且这两者必须配对出现。

MQPUT
把消息放到一个打开的队列中。

MQPUT1
也是把消息放到一个打开的队列中。不过它比 MQPUT 多执行了两个函数:MQOPEN 和 MQCLOSE。

MQGET
从一个打开的队列中读取或浏览信息。在它的参数当中,有一个 MQGMO 的参数很重要,可以用来指示该操作是读取还是浏览的,如果是读取的,则从队列中读走消息;如果是浏览的,则消息还留在队列中。因为要提供一个 buffer 以及该 buffer 的长度给 MQGET 用来存放读取的消息,如果消息太长,buffer 存放不下,也可以设定该参数告诉 MQGET 到底是返回部分消息还是操作失败。

MQBEGIN

The MQBEGIN MQI function is only used when a queue manager has been configured to coordinate global units of work involing database products.

MQCMIT 和 MQBACK
MQCMIT 用来提交当前 unit of work。对局部的 unit of work 而言,仅仅包括 MQ 的操作:从应用程序连接到队列管理器或才最后一次执行 MQCMIT/MQBACK 以来的所有在同步点之下执行的 MQGET/MQPUT 操作。对全局的 units of work 而言,它包括数据库操作和 MQ 操作。
MQBACK 用来回滚当前 unit of work。这些操作和 MQCMIT 描述的操作相同。MQBACK 会导致所有的操作被撤销,put 到队列的消息会被移除掉,从队列 get 的消息则会重新返回到队列中。

MQINQ 和 MQSET
MQINQ 查询属性,而 MQSET 则设置属性。

以上每一个函数调用都返回一个 completion code 和一个 reason code。completion code 只有三种值:
1. MQCC_OK: 表示函数调用完全成功。
2. MQCC_WARNING: 表示函数调用部分完全。可以查看 reason code 了解更多的细节。
3. MQCC_FAILED: 表示函数调用失败。可以查看 reason code 了解更多的细节。
而 reason code 的值则有很多。具体的细节的可查看reason code list。

mqclient

因为工作的需要,所以自己封装了 MQI 13 个函数中的部分接口。目前 mqclient(这里可以查看) 库只提供了 6 个接口:

1 2 3 4 5 6 
int mqclient_connect(); int mqclient_disconnect(); int mqclient_get_open(); int mqclient_get(); int mqclient_put_open(); int mqclient_put();  

一开始是把两个 open() 函数放在 put() 和 get() 里面的,但考虑到每 get() 一次都要 open() 和 close() 一次,会不会不够高效呢?如果把两个 open() 函数独立出来,那只调用一次 open() 后就可以连续的 get() 了。所以就把它们独立出来。而 close() 则放在 disconnect() 里面。

在使用的过程中发现,将 mqclient_get_open() 和 mqclient_put_open() 独立出来,会导致当使用同一个 struct mqclient 结构时,如果要操作多条写或读队列,则只有最后调用这两个接口的那条队列可以操作成功。例如有两条队列 Q1 Q2 都要进行 put() 操作,

1 2 3 4 
mqclient_put_open(&mqc, "Q1", NULL); mqclient_put_open(&mqc, "Q2", NULL); mqclient_put(&mqc, "hello", strlen("hello")); // put to Q1 mqclient_put(&mqc, "world", strlen("world")); // put to Q2  

但实际所有的操作都是对 Q2 进行的。当然可以先操作完 Q1 再操作 Q2。这里只是把一条消息添加到 Q1 和 Q2 上,但如果有多条消息分别要添加到 Q1 和 Q2 上呢,并且逻辑一定要先往 Q1 put 一条消息后再往 Q2 put 一条消息。这时就不得不要再添加一个 struct mqclient 结构了。然后代码就要写成:

 

1 2 3 4 5 6 
mqclient_put_open(&mqc1, "Q1", NULL); mqclient_put_open(&mqc2, "Q2", NULL);  { ... // put msgs to Q1 and Q2 loop } 

 

 

IBM MQ常用命令

常用命令
创建队列管理器
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)

常用补充命令
显示队列管理器 dspmq
显示文件名 dspmqfls

启动本地队列管理器 strmqm
结束本地队列管理器 endmqm
启动通道启动进程 runmqchi/runmqchl

 

原创粉丝点击