我们的Rebus / RabbitMQ设置存在问题,Rebus突然停止从RabbitMQ检索/处理消息。这种情况在上个月发生了两次,我们不确定如何继续。
我们的RabbitMQ设置在不同的服务器上有两个节点,Rebus端是一个Windows服务。
我们发现Rebus或Rebus运行的服务器上的事件日志中没有错误。 我们也没有在RabbitMQ服务器上看到错误。
Rebus(以及Windows服务)继续运行,因为我们看到其他日志消息,如DueTimeOutSchedular和timeoutreplies。但是,似乎工作线程停止运行,但没有记录任何错误。
它会导致RabbitMQ输入队列不断增长:(我们正在添加日志记录来监控它,以便我们在再次发生时收到通知。
但我正在寻找有关如何继续“调查”以及如何防止这种情况的想法的建议。也许有些人以前经历过这个?
更新 看来我们确实有一个节点崩溃,至少在最后一次发生时。主RabbitMQ节点崩溃(服务器崩溃),从服务器被提升为主服务器。据我所知,节点上的RabbitMQ日志一切都按计划进行。 RabbitMQ日志中没有其他错误。
在发生这种情况时,Rebus被配置为仅连接到从属节点(然后提升为主节点),因此Rebus没有遇到rabbitmq故障,因此没有Rebus连接错误。但是,似乎Rebus在发生故障时停止处理消息。
我们实际上是在几个队列中遇到这种情况,其中一些,但并非所有队列似乎都处于非同步状态。
更新2 我能够很容易地重现问题,所以它可能是我们设置中的配置问题。但这就是我们重现它的方法
队列是镜像的
我们有两个小测试应用程序来重现这个,一个“发送者”每秒发送一条消息,一个“消费者”处理这些消息。
当 rabbit1 关闭时,“使用者”会停止处理邮件,但“发件人”会继续发送邮件并且队列会不断增长。
这没有效果,“消费者”仍然无法处理消息。
当“consumer”重新启动时,它会检索所有消息并处理它们。
我认为我已正确遵循设置指南,但这可能是我们配置问题。我似乎无法找到任何可能表明我们做错了什么。
Rebus仍然连接到RabbitMQ,我们看到在管理站点的连接选项卡中,“消费者”发送/接收的B / s在停止处理消息时降至约2 B / s
更新3 好的,所以我下载了Rebus源并附加到我们的进程,所以我可以看到“RabbitMqMessageQueue”类停止时会发生什么。当“rabbit1 *关闭”时,“BasicDeliverEventArgs”为空,这是代码
BasicDeliverEventArgs ea;
if (!threadBoundSubscription.Next((int)BackoffTime.TotalMilliseconds, out ea))
{
return null;
}
// wtf??
if (ea == null)
{
return null;
}
请参阅:https://github.com/rebus-org/Rebus/blob/master/src/Rebus.RabbitMQ/RabbitMqMessageQueue.cs#L178
我喜欢“wtf ??”评论:)
答案 0 :(得分:3)
听起来很奇怪!
每当Rebus的RabbitMQ传输在连接上出现错误时,它将丢弃连接,等待几秒钟,并确保在可能的情况下再次重新建立连接。
您可以在此处查看来源中的相关位置:https://github.com/rebus-org/Rebus/blob/master/src/Rebus.RabbitMQ/RabbitMqMessageQueue.cs#L205
所以我想问的问题是RabbitMQ客户端库是否可以以某种方式静默地进入故障状态,而不会在Rebus尝试获取下一条消息时抛出异常......?
当您遇到错误时,您是否查看了RabbitMQ管理界面中的“连接”标签,看看客户端是否仍然连接?
<强>更新强>
感谢您彻底调查:)
“wtf ??”是因为我曾经在ea
显然为空时经历了一次打嗝,这在当时是意料之外的,因此导致NullReferenceException
以后和我的日志中的异常呕吐。
根据the docs,Next
将返回true并在result
到达“end-of-stream”时将其设置为null,这显然是当底层模型是闭合。
在这种情况下Rebus的正确行为是抛出一个正确的异常并重新建立连接 - 我马上就会实现它!
请坐下,我会在几分钟内准备好你的补救措施!