【问题标题】:How do I set a number of retry attempts in RabbitMQ?如何在 RabbitMQ 中设置重试次数?
【发布时间】:2014-06-03 05:03:09
【问题描述】:

我正在使用 RabbitMQ,并且我有一个保存电子邮件消息的队列。我的消费者服务使消息出队并尝试发送它们。如果出于任何原因,我的消费者无法发送消息,我想将消息重新排队以再次发送。我意识到我可以做一个 basicNack 并将 requeue 标志设置为 true,但是,我不想无限期地重新排队消息(例如,如果我们的电子邮件系统出现故障,我不想不断地重新排队未发送的消息)。我想定义一个有限的次数,我可以将消息重新排队以再次发送。但是,当我将其出列并发送 nack 时,我无法在电子邮件对象上设置字段。队列中的消息上不存在更新的字段。还有其他方法可以解决这个问题吗?提前致谢。

【问题讨论】:

标签: .net queue rabbitmq consumer


【解决方案1】:

在 RabbitMQ(以及 AMQP 协议)中没有像重试尝试这样的功能。

实现重试尝试限制行为的可能解决方案:

  1. 如果之前没有重新发送消息,则重新发送消息(检查 basic.deliver 方法上的 redelivered 参数 - 你的库应该为此提供一些接口)并删除它,然后在 dead letter exchange 中捕获,然后以某种方式处理。

  2. 每次无法处理消息时再次发布消息,但设置或递增/递减标题字段,例如x-redelivered-count(不过,您可以选择任何您喜欢的名称)。要在这种情况下控制重新交付,您必须检查您设置的字段是否达到某个限制(顶部或底部 - 0 是我的选择,a-la ttl 在来自 tcp/ip 的 ip 标头中)。

  3. 在 Redis、memcache 或其他存储中存储消息唯一键(比如 uuid,但您必须在发布消息时手动设置),甚至在 mysql 中与重新传递计数一起存储,然后在每次重新传递时递增/递减此值直到达到极限。

  4. (对于真正的极客)编写将实现您想要的此类行为的插件。

#3 的优点是重新传递的消息保留在队列头中。如果您排长队或消息顺序对您很重要,这一点很重要(注意,重新投递会破坏严格的消息顺序,详情请参阅官方文档或this question on SO)。

附注:

本主题中有similar answer,但在php中。看一遍,也许对你有一点帮助(从“有多种技术可以处理循环重新传递问题”开始阅读。

【讨论】:

  • 非常感谢。我想我会走死信交换路线。
  • 另外,如果您不介意限制消息生命周期而不是限制重试次数,您可以随时设置 TTL。
  • 目前似乎无法编写插件。 rabbit 中没有任何行为可以让您挂钩消息消费并修改消息。您只能在发布期间使用 rabbit_channel_interceptor 修改消息头,但这在这里没有帮助。
【解决方案2】:

虽然这是一个老问题,但我认为您现在可以通过死信交换和x-death 标头数组的组合轻松做到这一点,一旦消息被死信:

死信进程将一个数组添加到每个死信消息的标题中,名为 x-death。该数组包含每个死信事件的条目,由一对 {queue, reason} 标识。每个这样的条目都是一个包含多个字段的表:

queue:消息之前所在的队列的名称 死信

reason:死字的原因,见下文

时间:消息被死信的日期和时间为 64 位 AMQP 0-9-1 时间戳

exchange - 消息发布到的交易所(请注意,如果消息是死信的,这将是死信交换 多次)

routing-keys:发布消息时使用的路由密钥(包括 CC 密钥但不包括 BCC 密钥)

count:由于这个原因,这条消息在这个队列中被死信的次数

original-expiration(如果消息由于每个消息的 TTL 而被死信):消息的原始过期属性。这 expire 属性从消息中的死信中删除 为了防止它在它被路由到的任何队列中再次过期。

阅读此great article 了解更多信息

查看此抽签:

【讨论】:

    【解决方案3】:

    在我看来,更好的想法是在消费者内部实现死信交换和重试逻辑的组合。如果消费者无法处理消息,那么您将消息放入 DeadLetterQueue

    您可以在下面找到使用 node-amqp 和 Rabbitmq https://github.com/kharandziuk/dead-letter-exchange-prototype 实现的死信交换原型。

    【讨论】:

    • 为简单起见 +1,但大型应用程序的缺点是 RAM 使用率更高,而消息位于消费者的 RAM 中等待重试(或者如果您限制正在处理的并发消息数,则吞吐量会降低到防止过多的 RAM 使用)。如果您打算缩短重试延迟并减少总尝试次数,可能效果最佳。
    猜你喜欢
    • 2021-07-14
    • 2020-05-07
    • 1970-01-01
    • 1970-01-01
    • 2016-01-13
    • 2021-07-09
    • 2017-07-22
    • 1970-01-01
    • 2019-10-04
    相关资源
    最近更新 更多