RabbitMq消息导致服务器崩溃,导致无限重试

时间:2019-08-22 08:56:30

标签: c# .net-core rabbitmq

我们使用Rabbit mq将消息发送到服务器进行处理。

我们要求服务器确认消息。这样,如果服务器在处理消息时碰巧死了,我们将在重新启动消息时或在其他服务器上重试该消息。

问题是,在极少数情况下,我们会收到一条确定性地使服务器崩溃的消息。这是因为我们调用了一些开源的本机dll,这些dll有错误,有时这些dll只会导致进程崩溃,没有异常。当然,修复这些错误将是理想的选择,但是我们不希望很快就修复pdfium或opencv中的所有此类问题。我们必须考虑一个事实,无论我们做什么,最终都会得到这样的信息。

其结果是,然后重试该消息,服务器重新启动,拾取该消息,崩溃,等等。在我们手动停止服务器并清除消息之前,没有任何处理。不理想。

我们该怎么解决这个问题?

我们不想做的是创建另一个服务来监视Rabbitmq服务,查找此类消息并清除它们,因为这只会导致复杂性不断提高。相反,我们希望在rabbitmq客户端级别处理此问题。我们很高兴地说,如果一条消息没有被处理3次,我们应该只是使该消息失败。我们可以通过维护已经处理过的消息的数据库条目来做到这一点,但是理想情况下,我不想涉及任何外部事务,而只在Rabbitmq客户端库中包含此问题的解决方案。我不确定如何做到这一点。

1 个答案:

答案 0 :(得分:3)

我在事件驱动的体系结构中使用的一种方法是使用死信交换(DLX)或中毒队列,这样,如果由于服务故障而多次看到同一条消息,那么它将被推送到DLX中重新排队到原始交换中。这些消息然后触发我们系统中的另一种类型的过程,以提醒我们消息被阻塞并且无法处理,然后我们可以诊断并修复使用者。修复后,我们触发另一个过程,将有毒消息移回原始交换,然后按常规进行处理。

在您的情况下,由于您的进程崩溃,有两种可能的方式来处理这些消息:

  1. 如果邮件被标记为已重新发送,则克隆邮件并将尝试计数添加到正文中或作为邮件的标头(x-attempt-count)。然后,该副本将与尝试计数一起添加到队列的后面。然后,当副本被耗尽时,您可以检查副本是否达到阈值,然后将消息移至DLX或存储在数据库中。这里的主要缺点是,它破坏了处理消息的顺序。

  2. 使用外部服务来跟踪传递尝试的次数,我建议您使用redis / memcache之类的方法,您可以在其中基于唯一的消息ID增加计数器。在过程开始时,如果消息已标记为已重新发送,则查找计数器。如果邮件已达到阈值,请再次触发另一个过程,例如将其移入DLX。