因项目使用到IBM MQ与其他服务器交换数据,在测试过程中,发现一直存在队列报错问题,大致报错内容如下:
Traceback (most recent call last):
MQError: MQRC_ALREADY_CONNECTED
后在多人帮助下发现,可能由于在于MQ交互过程的逻辑使得此问题的出现:
交互逻辑中,所使用到的是tornado框架下的ioloop定时器,已每20秒异步触发一次函数的方式去链接一次MQ:if __name__ == "__main__":
init_log()
app = make_app()
app.listen(9900, "127.0.0.1")
tornado.ioloop.PeriodicCallback(doTask, 1000 * 20).start()
tornado.ioloop.PeriodicCallback(doCompress, 1000 * 60 * 60 * 2).start()
tornado.ioloop.IOLoop.current().start()
链接MQ的逻辑为:import pymqi
queue_manager = 'QM1'
channel = 'DEV.APP.SVRCONN'
host = '127.0.0.1'
port = '1414'
queue_name = 'TEST.1'
message = 'Hello from Python!'
conn_info = '%s(%s)' % (host, port)
qmgr = pymqi.QueueManager(None)
qmgr.connect_tcp_client(queue_manager, pymqi.CD(), channel, conn_info)
try:
qmgr.connect_tcp_client(queue_manager, pymqi.CD(), channel, conn_info)
except pymqi.MQMIError as e:
if e.comp == pymqi.CMQC.MQCC_WARNING and e.reason == pymqi.CMQC.MQRC_ALREADY_CONNECTED:
# Move along, nothing to see here..
pass
queue = pymqi.Queue(qmgr, queue_name)
queue.put(message)
queue.close()
qmgr.disconnect()
[上述代码源于pymqi手册,链接如下](https://dsuch.github.io/pymqi/examples.html#how-to-avoid-mqrc-already-connected)
故,在第一次链接时,可能由于MQ中并无消息,这将导致链接后,反馈的MQ队列无消息错误:
Traceback (most recent call last):
pymqi。MQMIError:MQI Error,Comp:2,Reason 2033:MQRC_NO_AVAILABLE
此导致,链接过程的最后两步(断开队列,断开链接)并未执行,而直接跳转到下次链接过程
此处,在多人的帮助下,将手册中的代码改动后,目前验证情况下,并未再次发生链接时报错,MQ已经链接问题,具体改动内容看代码:
def connect():
recv_mq = {
"ip": "10.232.129.54",
"port": "1416",
"username": "mqm",
"password": "mqm",
"recv_queue_manager": "VMFSMESMQTEST1",
"recv_channel": "CLI.PD.MES.MEB.1"
}
host = recv_mq["ip"] + "(" + recv_mq["port"] + ")"
global qmgr
qmgr = pymqi.QueueManager(None)
# qmgr.connect_tcp_client(recv_mq["recv_queue_manager"], pymqi.CD(), recv_mq["recv_channel"], host,
# recv_mq["username"], recv_mq["password"])
try:
qmgr.connect_tcp_client(recv_mq["recv_queue_manager"], pymqi.CD(), recv_mq["recv_channel"], host,recv_mq["username"], recv_mq["password"])
except pymqi.MQMIError as e:
print("Connect to MQ Error:",e)
if e.comp == pymqi.CMQC.MQCC_WARNING and e.reason == pymqi.CMQC.MQRC_ALREADY_CONNECTED:
pass
def connectmq_put(recv_mq, str1):
queue = pymqi.Queue(qmgr, recv_mq["recv_queue"])
queue.put(str1)
queue.close()
#qmgr.disconnect()
def connectmq_get(recv_mq):
queue = pymqi.Queue(qmgr, recv_mq["recv_queue"])
str1 = queue.get()
queue.close()
#qmgr.disconnect()
return str1
将完整的循环逻辑拆分,定时器触发异步执行时,直接链接MQ服务器,并将链接引为全局,每次与MQ交互只链接队列,执行connectmq_put
或者connectmq_get
即可,待本次异步过程结束,使用先前声明的全局变量将链接断开即可:
qmgr.disconnect()
学习不易,身在其中,深有感悟!希望可以帮到大家