重复使用IBM.WMQ.MQQueue对象

5
我们正在使用.NET API来访问IBM的WebSphere MQ。
创建MQQueueManager对象显然是一项昂贵的操作,因此我们缓存并重复使用这些对象的池。
目前,对于每个请求,我们都会访问所需的队列:
//obtain queueManager from pool
IBM.WMQ.MQQueue requestQ= queueManager.AccessQueue(requestQName, mqOptions);
IBM.WMQ.MQQueue responseQ= queueManager.AccessQueue(responseQName, mqOptions);

完成后关闭它们:

requestQ.Close();
responseQ.Close();

这是最佳实践吗?还是我们应该在池化和重用MQQueue对象(除了队列管理器之外)?在客户端上,AccessQueue()似乎是一项廉价的操作。

1个回答

0
答案取决于您的线程模型和事务性。一般来说,消息客户端应始终使用事务性,即使只是单阶段提交。原因是,否则可能会导致重复或丢失消息的结果不明确。我在另一个答案中提供了更详细的解释。
问题在于事务是连接范围的。当您提交时,您为整个连接提交。安全地跨多个线程使用相同的连接将排除使用事务,从而使应用程序面临丢失或重复消息的风险。由于队列句柄仅在特定连接的上下文中有效,因此它们继承自您的线程模型和连接池。
服务提供者应用程序的最常见模型是在输入队列上每个线程维护一个连接,并动态打开/放置/关闭输出队列。例如,在单个工作单位中...
  1. 读取下一个请求消息
  2. 使用回复信息获取目标
  3. 打开回复队列
  4. 放置响应
  5. 提交
  6. 销毁回复目标对象,从而关闭回复队列

在这种情况下,连接不会被不断重建,输入队列也永远不会关闭。但是,它需要每个线程维护一个专用连接。


你说“连接”,具体指什么?我看IBM文档也提到了它,但是由于我认为我已经与QueueManager建立了“连接”,所以我不太明白是否需要为每个线程创建一个新的QM(缓存它)或者不需要。 - Bruno Brant
这个答案根本不涉及IBM的MQ实现 - 只要您(至少)没有提到,我就不会对其投下反对票。 - Florian Neumann
感谢您解释关于downvote的事情。如果答案依赖于MQ特定的行为,我会很乐意更新并指出这一点。然而,问题和答案都依赖于在IBM的实现中符合JMS规范并可以有效地在该上下文中描述的行为。当然,您可以对这种方法提出异议,我很感激您的解释,但我对所写的回答感到满意。 - T.Rob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接