【问题标题】:Something making NServiceBus lose messages使 NServiceBus 丢失消息的东西
【发布时间】:2012-03-19 22:35:20
【问题描述】:

我有一个 NServiceBus 配置,在开发人员机器和我的开发环境中运行良好。

但是,当我将它移到我的测试环境时,我的消息就开始被扔掉了。

系统如下:

  1. 应用从大型机系统获取 TCP 消息并将其发送到 MSMQ(称为 FromMainframe)。
  2. 托管在 IIS 中的应用程序具有用于该 MSMQ 的“Handle”方法并处理来自大型机的消息。

在我的测试环境中,第二步只进行了一半。消息从 MSMQ 中弹出,但未由我的应用程序处理。

实际上我的数据丢失了! NServiceBus 将它们从队列中删除,但我从未处理它们。他们甚至不在错误队列中!

这些是我尝试过的事情,试图弄清楚发生了什么:

  1. 检查配置文件
  2. 将远程调试器附加到进程以查看Handle 方法在做什么
    • 永远不会调用Handle 方法(但是当我附加到开发环境时,我的Handle 方法中的断点被命中,并且一切正常)。
  3. 将我的 Dev 版本重新部署到测试环境并再次尝试第 2 步(以防万一版本不完全相同。)
  4. 再次检查配置文件
  5. 检查错误队列没有填满
    • 错误队列保持为空(我希望它会填满,这样我的数据就不会丢失)。
  6. 检查可能从我的 MSMQ 中提取内容的任何其他进程
    • 我关闭了我的 IIS 网站,FromMainframe 队列中的消息开始备份。
    • 当我重新打开它时,消息消失得相当快(但仍然不是一次全部消失)。它们消失的速度太快了,我的Handle 方法无法处理它们。
  7. 再次检查配置文件。
  8. 运行 NServiceBusTools\MsmqUtils\Runner.exe \i
    • 我运行它,重新启动,一次又一次地运行它!
  9. 再次检查配置(我一定错过了什么吧?)
  10. 检查开发环境配置未指向测试环境
    • 我认为不可能使用另一台计算机的 MSMQ 作为您的输入队列,但检查一下也无妨。
  11. 寻找任何可能会悄悄杀死我的消息的 catch 块。
  12. 最后一次检查配置文件。
  13. 在另一台机器上重新创建我的测试环境(完美运行)
  14. 在 IIS 之外运行我的东西。
    • 当我在 IIS 外部托管(使用 NServiceBus.Host.exe)时,一切正常。所以它必须是 IIS 的事情,对吧?
  15. 疯狂并希望堆栈溢出可以提供任何形式的见解。

【问题讨论】:

  • NSB 是否在 IIS 内部托管?它配置了哪些协议?您的队列是事务性的吗? MSDTC 是否已启动并运行? App Pool 身份是否对队列具有正确的权限?消息是否最终进入系统死信队列?
  • 您是否配置了 log4net 以捕获所有 nservicebus 输出?您的答案可能就在其中。还有哪个版本的 nservicebus?
  • @AdamFyles - NSB 托管在 IIS 中。我需要检查协议(我认为这不会影响 NSB)。我的 MSMQ 是由 NSB 设置的。所以我认为它是事务性的。应用程序池确实具有正确的权限。消息不会在死信队列中结束。 (他们刚刚走了)
  • @Sarmaad - 我没有这样做。我也不知道该怎么做。如果你知道如何请张贴。 (如果没有,我会挖掘它。)我正在运行 NSB 2.6.0.1506
  • 你能从 IIS 外部的代码中读取队列吗?您还可以尝试在 MSMQ 中打开负源日志。这有助于您确定消息发生了什么。

标签: iis iis-7 nservicebus


【解决方案1】:

所以我对抛出“答案”的事情有足够的了解。

当我设置我的 NServiceBus 自托管时,我有一个调用来加载消息处理程序。

NServiceBus.Configure.With().LoadMessageHandlers()

(还有更多配置,但为了简洁我省略了)

当您调用它时,NServiceBus 会扫描程序集以查找实现 IHandleMessages<T> 的类。

因此,不知何故,在我的测试环境机器上,ServiceBus 对调用 IHandleMessages 的类的目录的扫描未能找到我的类(即使程序集绝对存在)。

事实证明,如果 NServiceBus 没有找到处理消息的东西,它会扔掉它!!!

在我看来,这完全是一个设计错误。 NServiceBus 的整个想法是不丢失您的数据,但在这种情况下,它就是这样做的!

现在,一旦您知道了这个陷阱,就有几种方法可以绕过它。

  1. 明确说明您的处理程序应该是什么:

    NServiceBus.Configure.With().LoadMessageHandlers<First<MyMessageType>>()

  2. 更进一步的保护是添加另一个处理“其他所有内容”的处理程序。 IMessage 是所有消息有效负载的基础,因此如果您在其上放置一个处理程序,它将拾取所有内容。
    如果您将 IMessage 设置为 handle after 您的消息得到处理,那么它将处理 NServiceBus 找不到处理程序的所有内容。如果您在 Handle 方法中抛出异常,这将导致 NServiceBus 将消息移动到 error 队列。 (我认为应该是 默认 行为。)

【讨论】:

  • 您的工作是在此处声明所有消息处理程序还是仅在消息处理程序集中声明一个?
  • @Galen - 我只有一个消息处理程序。我现在明确说明它在我的配置中是什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-28
  • 2013-01-25
相关资源
最近更新 更多