本文不介绍MQ的具体使用方法和概念对象,网上有不少文档资料,推荐大家看《精通 WebSphere MQ(完整版)》,在此主要介绍几种我日常运维使用到的一些调优方法。
官方给出的调优策略,大家可以参考:http://www.ibm.com/developerworks/cn/websphere/library/techarticles/0712_dunn/0712_dunn.html
一、 与API 调用有关的MQ性能考虑因素
这里,我们在讨论各个API对性能的影响时,均以C语言提供的API为例,其他开发语言与此类似。
1 关于MQCONN/MQDISC的使用
在MQ的13个函数中,MQCONN/MQDISC是最耗CPU的两个函数,其次是MQOPEN和MQCLOSE这两个函数,因此要尽量避免必要地重复使用这几个函数。比如,当您需要从队列中读取多条消息时,正确的编程方法应该如下:
MQCONN
MQOPEN
MQGET
.
.
.
MQGET
MQCLOSE
MQDISC
即:连接/断开队列管理器一次,打开/关闭队列一次,读取消息多次。而不应该反复建立与队列管理器的连接和反复进行队列打开/关闭操作。
2 MQCONNX的使用
通常,我们使用MQCONN这个函数建立与队列管理器的连接,除此之外,MQ支持trusted application binding,即fastpath binding,用MQCONNX来实现。当从性能方面考虑时,我们可以使用MQCONNX来提高性能。
在使用MQCONNX时,我们可以设置MQCNO(connect option)来指定连接方式。缺省情况下,该选项为MQCNO_STANDARD_BINDING,如果设置为MQCNO_FASTPATH_BINDING,即表明采用fastpath binding方式连接队列管理器,这种应用称为trusted application。所谓的trusted application,是指该应用程序和本地队列管理器代理组成同一个进程,从而提高性能。利用fastpath binding不仅能够提高连接队列管理器的性能,同时也能够提高mqopen,mqclose的性能。
3 消息大小对mqput, mqget函数耗时的影响
尽量减小消息的大小,小消息的读取效率要高。对于mqget, mqput这两个函数而言,8k以下的消息的耗时差别不大,8k到128k的消息的耗时随着消息大小的增加而增加。大于128k的消息耗时较大,因为当与队列相关的内存满了的时候,会有硬盘交换。
同时要注意,从传输效率而言,如果在广域网上进行消息传输,消息太小会影响传输效率,因为对于每一消息,MQ都会有一个消息头,它会占有一定的字节数,如果把消息拆分太小,每个消息的传输头都会占据一定的开销。
4 对一个空队列的open,close 操作比非空队列的同样操作耗时要多。
第一次open队列耗时比接下来的open 耗时要多,对本地队列和远程队列的open,close耗时基本相同。
5 使用MQCMIT对消息进行批处理
当处理一批消息时,可以采用MQCMIT函数,将若干消息作为一个完整的交易来处理,消息将作为一个batch统一提交,而不是一个个地分别提交,因此,可以提高性能。尤其对于永久性的消息效果更加明显。
6 使用Distribution List 方式来把相同的消息发往不同的目的地
大家知道,MQ适用于不同类型的应用。不仅可以实现"点对点"的通讯,还通过DistributionList支持"多点广播"应用,即能够将消息发送到多个目标站点。可以使用一个MQ函数调用将单一消息发送到多个目标站点,并确保为每一站点可靠地提供信息,减少了函数调用的个数。同时,MQ不仅提供了多点广播的功能,而且还拥有智能消息分发功能,在将一条消息发送到同一系统上的多个用户或队列时,MQ可以将消息的一个复制版本和该系统上接收者的名单发送到目标系统。目标系统在本地复制这些消息,并将它们发送到DistributionList上的队列,从而减少了网络的传输量。
7 当向队列管理器仅发送一条消息时,使用MQPUT1函数。
在MQ的13个函数中,MQPUT1实现了这样一种功能,即它合并了MQOPEN, MQPUT, MQCLOSE三个函数的功能,在打开队列并且只希望发送一条消息时,它的CPU消耗比上述三个函数相加要少。
8 用match correlation ID的方法取消息比不匹配性能要差。
二、 与队列属性有关的MQ性能考虑因素
1 消息的永久性和非永久性
大家知道,MQ的消息分为永久性消息和非永久性消息两种,永久性消息是保存在硬盘存储介质上的,需要纪录日志的;相反,非永久性消息是存储在内存中的,不需要硬盘读写,因此使用非永久性消息的性能比永久性消息的性能要高很多,具体而言,最大可以提高近十倍。要注意的是,只有永久性消息的可靠性是可以保证的,即在发生故障,如当系统重启或队列管理器重启时,可以保证不丢失。因此,应根据您的业务需求和网络状况来确定消息的属性。
2 调整队列的相关参数设置:
对于队列而言,除了可以通过MQSC的"define queue"命令设置它的属性之外,有另外两个参数直接影响队列的性能,而这两个参数只有通过qm.ini文件进行设定。它们分别是:队列文件的大小(Maximum amount of bytes in a queue)和为每一个队列的非永久性消息保留的内存大小(Maximum amount of memory reserved for non-persistent messages),它们的缺省值分别对应于DefaultQFileSize和DefaultQBufferSize这两个参数。
队列的定义存储在硬盘上,并且在队列被打开时申请资源。我们可以设置队列DafaultQFileSize和DafaultQBufferSize两个参数来确定队列的定义参数,这些参数在队列管理器重启时生效,下面分别给予描述。
1) 队列文件大小
缺省情况下,队列文件在硬盘上的大小最大是320M, 它会被预先分配195kb内存,这195kb内存会在队列打开时获得。队列文件的大小最大值可以达到1G bytes, 这可以通过设置DefaultQFileSize参数来设定,当其设为1G时,队列打开时会申请350kb内存。
2)非永久性消息对应的内存大小
缺省情况下,对每个队列而言,用来存储non-persistent消息的共享内存是64kb, 我们可以通过修改DafaultQBufferSize参数将其增加至1MB。在打开队列的时候,要申请如此数量的内存,因此它直接影响到队列管理器需要的内存资源的大小,包括实存和虚存。推荐值是把该值设制成64kb的两倍,即128kb。永久性消息是存在硬盘上的,而非永久性消息是存在内存中的,当设定的buffer不够时,要进行磁盘交换,速度就会减慢,把它扩大后,若不进行硬盘交换,读取队列的速度就会快。当然,对该参数的修改也取决于系统实际物理内存的大小。
修改这两个参数的方法是更改队列管理器配置文件qm.ini的相关参数,具体方法举例如下:
在qm.ini文件中增加如下一节: TuningParameters:
DefaultQBufferSize=128000
DefaultQFileSize =1000000000
3 队列的深度和队列上的消息的长度的设置也会影响性能。
对每一个队列而言,都会被分配一个设定的buffer size,当磁盘I/O很高时,说明队列的buffer size满了,从而产生了硬盘交换。每个消息的大小乘以队列的深度决定了队列上消息占内存的大小,可以增加队列的个数或者增加队列的buffer size来提高性能。
4 设置多个队列提高并行处理能力
例如在总部,可以针对每一个分支机构设置一个队列,采用多个应用程序读取这些队列;对于同一个队列,也可以采用多个进程/线程同时进行读取操作。
三、与日志有关的MQ性能考虑因素:
1 把MQ的log 和queue files 放在不同的文件系统上。即将/var/mqm/log, /var/mqm文件系统分开。
在安装MQ的时候,我们经常推荐大家创建两个文件系统,即/var/mqm/log和/var/mqm,为了提高MQ的性能,我们建议把这两个文件系统放在不同的物理磁盘上,以提高磁盘I/O的效率。这是由于,在记录数据日志时,MQ会同时更新位于/var/mqm下的队列文件以及位于/var/mqm/log下的数据日志,因此建议把它们放在不同的物理盘上。
2 扩大MQ的日志文件大小和个数
在qm.ini配置文件中,有一小节是专门控制MQ的系统日志的,如下所示:
Log:
LogPrimaryFiles=3
LogSecondaryFiles=2
LogFilePages=1024
LogType=CIRCULAR
LogBufferPages=17
LogPath=/var/mqm/log/QM1
其中,LogPrimaryFiles和LogSecondaryFiles指定了日志文件的个数,LogFilePages指定了每个日志文件的大小,LogBufferPages指定了日志缓冲区的大小,这些参数都可以影响MQ的性能。
MQ常用命令:
win下使用 dspmq.exe
uninx/linux 下
#su - mqm
#dspmq
创建队列管理器
crtmqm –q QMgrName
-q是指创建缺省的队列管理器
删除队列管理器
dltmqm QmgrName
启动队列管理器
strmqm QmgrName
如果是启动默认的队列管理器,可以不带其名字
停止队列管理器
endmqm QmgrName 受控停止
endmqm –i QmgrName 立即停止
endmqm –p QmgrName 强制停止
显示队列管理器
dspmq –m QmgrName
运行MQ命令
runmqsc QmgrName
如果是默认队列管理器,可以不带其名字
您现在已经创建了将消息从发送队列管理器 QM_ORANGE 发送到接收队列管理器 QM_APPLE 上的队列 Q1 所需的全部 WebSphere MQ 对象。下一个任务是发送测试消息。在发送机器(主管队列管理器 QM_ORANGE 的机器)上执行此任务。
使用 amqsput 样本程序来将消息放入您创建的队列。
在 Windows 上,缺省情况下样本程序随 WebSphere MQ 服务器或客户机一起安装。在 Linux 上,需要安装样本程序 RPM。
打开命令提示符,然后按照以下步骤操作:
启动 amqsput 样本程序,如下所示:
在 Linux 上,切换到 /opt/mqm/samp/bin 目录,然后输入命令:./amqsput Q1
在 Windows 上,输入命令:amqsput Q1
此时会显示以下消息:
样本 amqsput0 启动
目标队列为 Q1
在一行或多行上输入某些消息文本,然后按 Enter 键两次。此时会显示以下消息:
样本 amqsput0 结束
您在接收机器(主管队列管理器 QM_APPLE 的机器)上执行此任务。使用 amqsget 样本程序来从队列中取回消息。
打开命令提示符,然后按照以下步骤操作:
启动 amqsget 样本程序,如下所示:
在 Linux 上,切换到 /opt/mqm/samp/bin 目录,然后输入命令:./amqsget Q1
在 Windows 上,输入命令:amqsget Q1
此时会启动该样本程序,并显示您的消息以及此队列上的任何其它消息。在短暂停留后,样本程序结束,并再次显示命令提示符。
往队列中放消息
amqsput QName QmgrName
如果队列是默认队列管理器中的队列,可以不带其队列管理器的名字
从队列中取出消息
amqsget QName QmgrName
如果队列是默认队列管理器中的队列,可以不带其队列管理器的名字
启动通道
runmqchl –c ChlName –m QmgrName
启动侦听
runmqlsr –t TYPE –p PORT –m QMgrName
停止侦听
endmqlsr -m QmgrName
下面是在MQ环境中可以执行的MQ命令(即在runmqsc环境下可以敲的命令)
定义持久信队列
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)
以下是一些高级配置的命令:
amqmcert 配置SSL证书
amqmdain 配置windows上的MQ服务
crtmqcvx 转换数据
dmpmqaut 转储对象权限管理
dmpmqlog 转储日志管理
dspmq 显示队列管理器
dspmqaut 显示打开对象的权限
dmpmqcap 显示处理程序容量和处理程序数
dspmqcsv 显示命令服务器状态
dspmqfls 显示文件名
dspmqtrc 跟踪MQ输出(HP-UNIX LINUX Solaris)
dspmqrtn 显示事务的详细信息
endmqcsv 停止队列管理器上的命令服务器
strmqcsv 启动队列管理器上的命令服务器
endmqtrc 停止跟踪
rcdmqimg 向日志写对象的映像
rcmqobj 根据日志中的映像重新创建一个对象
rsvmqtrn 提交或逆序恢复事务
做MQ迁移的一个很好用的工具:
生产环境的QM由于某种需求,要更换服务器,又要保证在很短的时间内切换完成,那么怎么将原有定义的mq资源导出来,并形成ddl脚本呢?IBM提供了这么一个简单有效的导出工具(里面又各种平台的导出脚本),可以在ibm官方网站上搜索ms03,将它下载下来使用;注意要启动MQ的commandserver
a),解压:uncompress ms03_unix.tar.Z
tar -xvf ms03.tar
b),修改权限:进入到ms03目录,执行:chmod u+x saveqmgr.linux chown -Rf mqm:mqm ms03
c),导出数据(需要用mqm组用户):./saveqmgr.linux -m QM_860000 -f test.txt
其实saveqmgr.linux --help会得到更多的帮助,其中一个参数为:
--remoteQmgr | -r rqmgr : is the name of the remote qmgr (XMITQ name)
表示可以备份远程的队列管理器的名称,不过要在XMITQ里取得到。
--resetChannels | -R [flags] : create RESET CHANNEL commands
flags can be any combination of the follow to create RESET for that channel type:
s (SENDER) v (SERVER) r (RECEIVER) q (REQUESTER) c (CLUSSDR) d (CLUSRCVR)
the default is to create RESET commands for all the above channel types
可以重置通道,等等
d)恢复:先创建一个队列:crtmqm -q QM_860000
strmqm QM_860000
runmqsc QM_860000 < test.txt
okay,到此已经完全克隆了一份队列管理器,你可以放心使用了。通道可以runing。