C# WMQ:在多台机器上分发MQ读卡器

C# WMQ:在多台机器上分发MQ读卡器,c#,transactions,ibm-mq,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,

我正在使用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

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

MQ“默认情况下”不是事务性的-如果您想要事务性(或者与.net事务集成是另一个选项),则需要获得GMO_SYNCPOINT(MQ事务)并在连接(MQQueueManager级别)上提交


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

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

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

考虑一个将消息放入队列的应用程序。如果
PUT
调用接收到
2009连接断开
响应,则不清楚在channel agent接收并处理API调用之前或之后连接是否失败。应用程序无法分辨差异,必须重新放置消息以确保消息被接收。在syncpoint下执行
PUT
,可能会导致
COMMIT
上出现
2009
(或MQ以外的消息传输中的等效返回代码),并且应用程序不知道
COMMIT
是否成功,或者
PUT
是否最终将回滚。为了安全起见,它必须再次
放置该消息

现在考虑伙伴应用程序接收消息。在同步点之外发出的到达通道代理的

GET
将从队列中永久删除消息,即使通道代理随后无法传递消息。因此,使用事务会话可以确保消息不会丢失。但是假设消息已被接收和处理,并且
COMMIT
返回一个
2009连接断开
。应用程序无法知道该消息是在
提交过程中删除的,还是将回滚并再次发送。至少,该应用程序可以通过使用事务处理会话来检索消息来避免丢失消息,但不能保证永远不会收到重复消息

这当然是所有异步消息传递所特有的,而不仅仅是MQ,这就是JMS规范直接对其进行寻址的原因。除第4.4.13节“信息的重复生成”中的内容外,所有版本均说明了这种情况,其中说明:

如果在客户端提交其在服务器上的工作之间发生故障 会话和提交方法返回时,客户端无法确定 事务已提交或回滚。同样的歧义 在非事务性发送之间发生故障时存在 持久消息和发送方法的返回

由JMS应用程序来处理这种模糊性。在某些方面 在某些情况下,这可能会导致客户端生成功能上重复的 信息

由于会话恢复而重新传递的消息不可用 被认为是重复的消息

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

消息传输在传递给定消息的一个且仅一个副本时的行为是对传输可靠性的度量。相比之下,依赖于只接收一个消息副本的应用程序的行为是对应用程序可靠性的度量

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


另一方面,如果涉及灾难恢复,该应用程序还必须优雅地从丢失的消息中恢复,或者找到一种方法。

我不确定MQ到底是什么,但我认为它类似于Microsoft的消息队列。您真正需要避免冲突的是唯一的ID和解决冲突的方法。如果同时读取/更改了两条消息,则由宿主应用程序应用重要的业务规则。这与任何其他异步操作没有什么不同,在这种异步操作中,主机始终有责任说明问题所在,而客户端则有责任在情况发生时应用适当的工作流程。必须设计工作流程,这就是为什么