2008-11-20 33 views
4

我遇到了一个奇怪的情况:如果目标队列不存在,MSMQ会抛出邮件?

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

ServerB崩溃。我们必须重新格式化。当我们提起它时,我们忘了安装MSMQ服务。

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

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

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

问题是:这真的是我们应该从MSMQ期望的真实行为吗?我会认为,更多的防御性设计方法会让ServerB拒绝这些消息,而不是将其丢弃。

回答

2

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

从MSMQ文档:

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

的原因似乎是,MSMQ是为了用作异步传输使发送方发送,然后许多不同的东西可以前进的道路上发生的造成该消息不被传递。 它看起来像检查确定的唯一方法是寻找返回的否定确认消息。我们从未使用过这些。 您可以开始使用它们,或者尝试不进行远程发送。

Usenet thread discussing this.

1

它真的很大程度上取决于您使用的是什么类型的队列以及您向MSMQ询问消息的保证。请记住,MSMQ中的消息有时间可以在消息传输过程中(甚至是读取限制的时间)过期。

根据您配置发件人的方式,无法发送的邮件可能会将邮件设置为死信队列,因此我一定会在两台服务器上检查以查看发生了什么。

如果这是您想要更好地处理的情况,您可以要求MSMQ做更多。例如,您可以要求它将发送邮件的副本保留在日记队列中(然后根据需要自行排空邮件)。或者你可以要求它对消息传递的正面或负面的ACK,或者甚至要求它读取消息。在这些情况下,ACK/NACK被发送到您自己的应用可以监控和响应的您选择的管理队列。

0

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

实施例:

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