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

时间:2015-03-11 13:43:18

标签: c# transactions ibm-mq

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

我们正在考虑在多台机器上分发我们的服务,然后我们需要确保两台不同机器上的两个服务无法同时读取/获取相同的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事务,还是我需要在配置中更改以启用此功能?

或者 - 我是否需要让我们的大型机人员做一些他们的魔术?

THX

2 个答案:

答案 0 :(得分:4)

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

MQ默认情况下不是事务性的 - 如果你想要事务性(或者与.net事务集成是另一种选择),你需要使用GMO_SYNCPOINT(MQ事务)并在连接(MQQueueManager级别)提交

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

答案 1 :(得分:2)

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

也就是说,MQ或任何其他异步消息传递必须处理会话处理和模糊结果。这些因素的影响是任何异步消息传递应用程序都应该设计为优雅地处理欺骗消息。

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

现在考虑接收消息的合作伙伴应用程序。在同步点外部发出的到达通道代理的PUT将永久删除队列中的消息,即使通道代理无法提供该消息也是如此。因此,使用事务处理会话可确保消息不会丢失。但是假设已收到并处理了邮件,GET会返回COMMIT。该应用无法知道该消息是在2009 Connection Broken期间被删除还是将被回滚并再次发送。至少应用程序可以通过使用事务处理会话来检索它们来避免丢失消息,但不能保证永远不会收到欺骗。

这当然是所有异步消息传递的特有,而不仅仅是MQ,这就是JMS规范直接解决它的原因。所有版本都解决了这种情况,但在JMS 1.1 spec查看 4.4.13重复制作邮件一节中说明:

  

如果客户端在a上工作时发生故障   Session和commit方法返回,客户端无法确定是否   事务已提交或回滚。同样含糊不清   当非事务性发送a之间发生故障时存在   PERSISTENT消息和发送方法的返回。

     

由JMS应用程序来处理这种歧义。在一些   这种情况,这可能会导致客户产生功能上的重复   消息。

     

由于会话恢复而重新传递的消息不是   被视为重复的消息。

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

传递给定邮件的一个且仅一个副本的邮件传输的行为是传输可靠性的度量。相反,依赖于接收消息的一个且仅一个副本的应用程序的行为是应用程序可靠性的度量。

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

在相关说明中,如果涉及灾难恢复,应用程序还必须正常从丢失的邮件中恢复,或者找到violate the laws of relativity的方法。