WMQ:在多台机器上分发 MQ 读取器

WMQ: Distributing MQ readers over several machines

我正在使用 WMQ 访问大型机上的 IBM WebSphere MQ - 使用 c#。

我们正在考虑将我们的服务分散到多台机器上,然后我们需要确保两台不同机器上的两个服务不能同时 read/get 相同的 MQ 消息。

我获取消息的代码是这样的:

var connectionProperties = new Hashtable();

const string transport = MQC.TRANSPORT_MQSERIES_CLIENT;
connectionProperties.Add(MQC.TRANSPORT_PROPERTY, transport);
connectionProperties.Add(MQC.HOST_NAME_PROPERTY, mqServerIP);
connectionProperties.Add(MQC.PORT_PROPERTY, mqServerPort);
connectionProperties.Add(MQC.CHANNEL_PROPERTY, mqChannelName);

_mqManager = new MQQueueManager(mqManagerName, connectionProperties);

var queue = _mqManager.AccessQueue(_queueName, MQC.MQOO_INPUT_SHARED + MQC.MQOO_FAIL_IF_QUIESCING);
var queueMessage = new MQMessage {Format = MQC.MQFMT_STRING};
var queueGetMessageOptions = new MQGetMessageOptions {Options = MQC.MQGMO_WAIT, WaitInterval = 2000};
queue.Get(queueMessage, queueGetMessageOptions);

queue.Close();
_mqManager.Commit();
return queueMessage.ReadString(queueMessage.MessageLength);

默认情况下 WebSphere MQ 是事务性的,还是我需要更改我的配置才能启用它?

或者 - 我是否需要请我们的大型机人员施展魔法?

感谢

除非您主动浏览消息(即阅读但不锁定),否则只有 getter 能够 'get' 消息。即使没有事务性,MQ 仍然只会传递一次消息......但是一旦传递它就消失了

MQ 不是事务性的 'by default' - 如果您想要事务性(或与 .net 事务集成是另一种选择)

如果你使用同步点,那么一个 getter 会收到消息,另一个会忽略它,但如果你随后遇到问题并回滚,那么它会提供给任何 getter (如你所愿)。在这种情况下,您可能会看到一条消息两次,但那是因为您中止了事务,因此要求将其恢复到获取之前的状态。

我希望我能早点找到它,因为接受的答案不完整。如其他答案和 IBM 文档中所述,MQ 只提供一次消息传递。如果您有许多客户端在同一个队列上侦听,MQ 将只传送消息的一个副本。这是无可争议的。

也就是说,MQ 或与此相关的任何其他异步消息传递必须处理会话处理和不明确的结果。这些因素的影响使得任何异步消息传递应用程序都应设计为优雅地处理重复消息。

考虑将消息放入队列的应用程序。如果 PUT 调用收到 2009 Connection Broken 响应,则不清楚连接失败是在通道代理收到并处理 API 调用之前还是之后。应用程序无法区分,必须再次发送消息以确保收到消息。在同步点下执行 PUT 会导致 COMMIT 上的 2009(或 MQ 以外的消息传递传输中的等效 return 代码)并且应用不知道COMMIT 成功或如果 PUT 最终将被回滚。为了安全起见,它必须 PUT 再次发送消息。

现在考虑接收消息的伙伴应用程序。在到达通道代理的同步点之外发出的 GET 将从队列中永久删除消息,即使通道代理随后无法传递它。因此使用事务处理会话可确保消息不会丢失。但是假设消息已经被接收和处理并且 COMMIT return 是 2009 Connection Broken。应用程序无法知道消息是在 COMMIT 期间被删除,还是将被回滚并再次发送。至少应用程序可以通过使用事务处理会话检索消息来避免丢失消息,但不能保证永远不会收到欺骗。

这当然是所有异步消息传递所特有的,而不仅仅是 MQ,这就是 JMS 规范直接解决它的原因。所有版本都解决了这种情况,但在 JMS 1.1 spec 中查看 4.4.13 重复生成消息 部分,其中指出:

If a failure occurs between the time a client commits its work on a Session and the commit method returns, the client cannot determine if the transaction was committed or rolled back. The same ambiguity exists when a failure occurs between the non-transactional send of a PERSISTENT message and the return from the sending method.

It is up to a JMS application to deal with this ambiguity. In some cases, this may cause a client to produce functionally duplicate messages.

A message that is redelivered due to session recovery is not considered a duplicate message.

如果应用程序只接收一份消息副本至关重要,请使用两阶段事务。事务管理器和 XA 协议将提供非常强大(但仍然不是绝对)的保证,即应用程序只会处理消息的一个副本。

传递给定消息的一份且仅一份副本的消息传输行为是衡量传输可靠性的一种方法。相比之下,应用程序依赖于收到一份且仅一份消息副本的行为是应用程序可靠性的衡量标准。

从 IBM MQ 传输接收到的任何重复消息几乎肯定是由于应用程序未能使用 XA 来解释异步消息传递中固有的模糊结果,而不是 MQ 中的缺陷。当应用程序的生产版本因第一条重复消息而阻塞时,请记住这一点。

相关说明,如果涉及灾难恢复,应用程序还必须从丢失的消息中正常恢复,否则找到一种方法 violate the laws of relativity