如果目标队列不存在,MSMQ会丢弃消息?

时间:2008-11-20 20:10:33

标签: msmq

我遇到了一个奇怪的情况:

消息从ServerA发送到ServerB。它进入ServerA传出队列,然后发送到ServerB的队列。

ServerB崩溃了。我们不得不重新格式化。当我们提出它时,我们忘了安装MSMQ服务。

消息开始在ServerA的传出队列中起作用,直到发送消息的程序引发资源不足异常。

我们注意到错误并将MSMQ服务安装到ServerB上。 ServerA开始立即清空其传出队列。

当我们启动程序来处理ServerB上的消息时,它无法连接。我们了解到忘记在ServerB上创建队列。然而,到了这个时候,为时已晚。驻留在ServerA队列中的所有900K消息都已发送到ServerB。据我所知,ServerB将它们扔掉了,因为它没有配置目标队列。我已经知道正确的解决方案是在我们完全设置ServerB之前停止ServerA上的队列。

问题是:这真的是我们应该从MSMQ中获得的真实行为吗?我会认为更加防御性的设计方法是让ServerB拒绝这些消息而不是把它扔掉然后扔掉。

3 个答案:

答案 0 :(得分:2)

打开队列以将消息发送到远程计算机时(当dwAccess设置为MQ_SEND_ACCESS时),消息队列不会检查队列是否存在。

来自MSMQ文档:

http://msdn2.microsoft.com/en-us/library/ms699817.aspx

原因似乎是MSMQ旨在用作异步传输,因此发送方发送,然后可能会发生许多不同的事情,导致消息无法传递。 看起来确定的唯一方法是查找返回的否定确认消息。我们从未使用过这些。 您可以开始使用它们,也可以尝试不进行远程发送。

Usenet thread discussing this.

答案 1 :(得分:1)

这实际上很大程度上取决于您使用的是哪种队列以及您向MSMQ请求消息的保证。请记住,MSMQ中的消息有时间可以在消息传输过程中到期(或甚至是时间读取限制)。

根据您配置发件人的方式,无法传递的邮件可能会使其成为死信队列,所以我肯定会检查两台服务器上的邮件,看看那里发生了什么。

如果您希望更好地处理这种情况,您可以要求MSMQ做更多事情。例如,您可以要求它在日志队列中保留已发送消息的副本(然后根据需要自行排除)。或者您可以询问它是否有关于消息传递的正面或负面的ACK,甚至是要读取的消息。在这些情况下,ACK / NACK将发送到您选择的管理队列,您自己的应用可以监控并响应。

答案 2 :(得分:0)

我们有类似的行为,消息消失了。我注意到,如果'UseDeadLetterQueue'设置为true,至少在传输失败时,它会在源系统的死信队列中保留一份副本。

示例:

var message = new System.Messaging.Message();
message.UseDeadLetterQueue = true;