【问题标题】:Random Messages Not Being Handled in RebusRebus 中未处理的随机消息
【发布时间】:2018-12-18 21:24:33
【问题描述】:

我在实施 Rebus 时遇到了一个奇怪的问题,该问题在过去几年一直在运行,没有任何问题,我正在尝试找出问题的范围以及我的故障排除工作的重点。一点背景:

  • 我们一直在运行 0.99.66 版
  • 上周移至版本 3.1.5,然后发现问题出现
  • 回滚到 0.99.66,问题继续
  • 使用 MSMQ 进行传输
  • 运行 Windows Server 2016
  • 在其他服务器实例上运行相同的代码没有问题

因此,我们遇到了看似随机的情况,其中消息失败,最终进入错误队列并出现 Rebus 错误,表示无法将消息分派给任何处理程序。这可能会发生一次,但是当下次出现相同的消息类型时,它会被正确处理。

这是相关代码的 sn-p:

public class ProcessManagerService
{
    public ProcessManagerService()
    {
        ...

        BusAdapter = new BuiltinHandlerActivator();
        BusAdapter.Handle<FileEventMessage>(async msg => await StartProcess(msg));
        BusAdapter.Handle<ProcessRequest>(async msg => await StartProcess(msg));

        Bus = Configure.With(BusAdapter)
                .Logging(l => l.ColoredConsole(LogLevel.Error))
                .Transport(t => t.UseMsmq(ConfigurationManager.AppSettings["Queue"]))                   
                .Start();            
    }

    ...

    public async Task StartProcess(FileEventMessage msg)
    {
        var svc = new StepManager() { FileEvent = msg.FileEvent };
        await svc.Run();
    }

    public async Task StartProcess(ProcessRequest msg)
    {
        var svc = new StepManager();
        await svc.Run(msg);
    }
}

这里是一个抛出异常的例子:

5 个未处理的异常:2018 年 12 月 18 日上午 7:53:00 -06:00: Rebus.Exceptions.RebusApplicationException:带有 ID 的消息 c72a8b6d-e31c-4a88-937e-612bf1db8b11 和类型 ClearStone.Messages.Monitoring.File.FileEventMessage, ClearStone.Messages 无法发送到任何处理程序 Rebus.Pipeline.Receive.DispatchIncomingMessageStep.d__1.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 Rebus.Sagas.LoadSagaDataStep.d__7.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 Rebus.Pipeline.Receive.ActivateHandlersStep.d__3.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 Rebus.Pipeline.Receive.DeserializeIncomingMessageStep.d__2.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 Rebus.Pipeline.Receive.HandleDeferredMessagesStep.d__12.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 Rebus.Retry.Simple.SimpleRetryStrategyStep.d__8.MoveNext()


更新:这是在 Rebus 源中接线后更详细的堆栈跟踪:


5 个未处理的异常:2018 年 12 月 20 日上午 9:39:05 -06:00:Rebus.Exceptions.RebusApplicationException:ID 为 84c3605a-41de-4300-9596-97e7288d2bcb 并键入 ClearStone.Messages.Monitoring.File 的消息.FileEventMessage,ClearStone.Messages 无法分派给任何处理程序 在 Rebus.Pipeline.Receive.DispatchIncomingMessageStep.d__1.MoveNext() 在 C:\Temp\rebus_0_99_66_archive\Rebus\Pipeline\Receive\DispatchIncomingMessageStep.cs:line 61 --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.GetResult() 在 C:\Temp\rebus_0_99_66_archive\Rebus\Sagas\LoadSagaDataStep.cs:line 77 中的 Rebus.Sagas.LoadSagaDataStep.d__7.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.GetResult() 在 Rebus.Pipeline.Receive.ActivateHandlersStep.d__3.MoveNext() 在 C:\Temp\rebus_0_99_66_archive\Rebus\Pipeline\Receive\ActivateHandlersStep.cs:line 48 --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.GetResult() 在 Rebus.Pipeline.Receive.DeserializeIncomingMessageStep.d__2.MoveNext() 在 C:\Temp\rebus_0_99_66_archive\Rebus\Pipeline\Receive\DeserializeIncomingMessageStep.cs:line 36 --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.GetResult() 在 Rebus.Pipeline.Receive.HandleDeferredMessagesStep.d__12.MoveNext() 在 C:\Temp\rebus_0_99_66_archive\Rebus\Pipeline\Receive\HandleDeferredMessagesStep.cs:line 114 --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.GetResult() 在 C:\Temp\rebus_0_99_66_archive\Rebus\Retry\Simple\SimpleRetryStrategyStep.cs:line 105 中的 Rebus.Retry.Simple.SimpleRetryStrategyStep.d__8.MoveNext() 处

假设很明显并且它是这个特定的服务器实例/环境中的某些东西,我试图弄清楚为什么 Rebus 会以这种方式行事,以及我的环境中可能导致这种情况的原因。任何关于从哪里开始寻找的方向都将不胜感激!

【问题讨论】:

    标签: c# msmq rebus


    【解决方案1】:

    听起来很奇怪 :) 当人们遇到这个问题时,几乎总是因为他们以某种方式设置了多个 Rebus 实例来使用同一队列中的消息。

    在极少数情况下,这是因为在将处理程序添加到容器/内置处理程序激活器之前在总线上调用了.Start(),但这似乎不是问题你的情况。

    你能告诉我更多关于你的设置吗?如果它与您在上面显示的一样简单,也许您可​​以在单独的应用程序中重现它?

    【讨论】:

    • 感谢您回复我!所以,真的就是这么简单。使这特别困难的是,相同的代码在其他 2 个实例中运行没有问题。在这一点上,我试图排除我能做的事情——你能想到 MSMQ 可能导致什么吗?我需要在追逐代码之前排除环境因素。上面的 sn-p 实际上是 Rebus 实现的范围。它确实感觉环境,MSMQ 是一个外部依赖项。我们的计划是转移到 SQL 提供程序,这可能是我们在这种情况下要研究的下一步。
    • 对于多个实例,这是唯一消耗这些消息/指向该队列的实例。 Start() 是最后一次调用的 ;-) -- 几年前我在开始使用 Rebus 时遇到了这种情况。
    • 我解决了这个问题。 2 个总线实例共享同一个队列——一个用于发送,另一个用于接收。使用队列接收的实例存在于一个类中,该类由另一个使用该队列发送消息的类的实例实例化。我修改了“接收”实例以使用另一个队列并解决了问题。现在我只需要弄清楚为什么会发生这种行为就可以了;-)
    • 完美,感谢您花时间用您的发现更新问题 :) 不过有一件事:当您说“使用队列发送”时,听起来您的理解有点不对劲对我来说......如果你有一个只发送消息的总线实例,它没有理由有一个输入队列,因此你应该将它配置为单向客户端 (.Transport(t =&gt; t.UseMsmqAsOneWayClient()))
    • 感谢您的澄清——这完全有道理并回答了我一段时间以来的问题? 将其标记为答案,因为它实际上是多个实例消耗来自同一队列的消息。
    猜你喜欢
    • 2013-05-26
    • 2015-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多