如何在RabbitMQ中设置多次重试?

时间:2014-04-18 16:39:42

标签: .net queue rabbitmq consumer

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

3 个答案:

答案 0 :(得分:57)

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

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

  1. 如果以前没有重新传递Redeliver消息(检查redelivered方法上的basic.deliver参数 - 您的库应该有一些接口)并删除它然后捕获{{3}然后以某种方式处理。

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

  3. 在Redis,memcache或其他存储中存储消息唯一键(比如uuid,但你必须手动设置它),即使在mysql旁边还有重新计数,然后在每次重新传递增量/减量时价值直到达到极限。

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

  5. #3 的专业人员是重新传递的消息留在队列头部。如果你有很长的队列或者消息顺序对你很重要,那么这很重要(注意,重新发送会破坏严格的消息顺序,详见官方文档或dead letter exchange)。

    P.S。:

    本主题中有this question on SO,但在php中。仔细看看,也许它会对你有所帮助(从&#34开始阅读;有多种技术可以解决循环再生问题"

答案 1 :(得分:0)

尽管这是一个老问题,我认为您现在可以通过将死信交换和消息死信后添加的x-death标头数组结合起来轻松地做到这一点:

  

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

     

queue:消息之前所在的队列的名称   固定字母

     

原因:刻字失效的原因,见下文

     

time:消息失效的日期和时间,以64位AMQP 0-9-1时间戳为字母

     

exchange-消息发布到的交换(请注意,如果消息是不带字母的,这将是一个不带字母的交换   多次)

     

路由键:发布消息的路由键(包括CC密钥,但不包括BCC密钥)

     

计数:由于这个原因该消息在该队列中被死信了多少次

     

原始过期时间(如果邮件由于每个邮件的TTL而被废弃):邮件的原始过期属性。的   过期属性已从邮件中的死信中删除   为了防止它在路由到的任何队列中再次过期。

PS:您也可以使用投放标签字段

阅读此great article以获得更多信息

检查本次抽奖:

enter image description here

答案 2 :(得分:0)

从我的角度来看,这里更好的主意是在使用者内部实现死信交换和重试逻辑的组合。如果使用者无法处理消息,则可以将消息放入DeadLetterQueue

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