RabbitMQ中如何处理prefetch和'redelivered'的冲突
In RabbitMQ, how to handle the conflict between prefetch and 'redelivered'
基本上我遇到了与这里类似的问题:
http://rabbitmq.1065348.n5.nabble.com/Consumer-crash-redelivery-and-prefetch-td34103.html
我想预取一些消息以提高性能。
同时,如果一条消息失败,我确实想给它第二次机会(重试两次),目前我使用 'redelivered' 标志来实现它。如果不设置'redelivered',我会重新排队消息,否则我会放弃消息。
如果消费者因为尚未处理但 'redelivered' 标志将被设置而崩溃,这将导致那些预取消息(尚未处理)出现问题。
有什么解决办法吗?或者任何其他更好的方法来为 RabbitMQ 消息实现重试逻辑?
谢谢,
我发现此逻辑有几个问题,其中一个您已经指出。首先,redelivered
标志是一个非常无用的字段 - 它为无状态操作提供状态指示(处理消息不需要提供任何 "outside" 信息)。通常,您的消息处理器不应该关心消息是否已传递 1 次、10 次或 100 次 - 消息的处理和相关行为不应取决于传递的次数。
另一个更微妙的问题是,您有几种不同的故障模式,具有不同的影响,并且您发现将所有这些都减少到一个 redelivered
布尔值。
您可以做几件事:
首先,您应该尝试区分由格式错误的消息引起的故障和由服务器的临时情况引起的故障。前者将永远无法被处理(并且应该被彻底拒绝),而后者可能会在条件解决后被处理。现在,您如何在两者之间做出选择?你如何决定在重试之前等待多长时间?
其次,如果您确实需要了解之前的失败,您可以在消息中添加 header 和 re-publish(而不是添加 basic.reject
)。该消息将转到 queue 的后面,但此状态信息现在将成为消息的一部分,可供未来的处理器使用。
如果这是 request-reply 场景,则只需拒绝消息并让客户端重试请求。显然,如果客户端无法知道 when/if 消息已被处理,这是不可取的。
您是否考虑过使用 dead letter exchange?
基本上,您不会将失败的消息重新排队,而是拒绝它。
如果您配置了死信交换,则可以为该被拒绝的消息设置一个新流,例如将其放在您的进程也订阅的另一个队列中。
有了这样的机制,所有的消息都会至少被处理两次,这似乎是你的目标。
基本上我遇到了与这里类似的问题:
http://rabbitmq.1065348.n5.nabble.com/Consumer-crash-redelivery-and-prefetch-td34103.html
我想预取一些消息以提高性能。 同时,如果一条消息失败,我确实想给它第二次机会(重试两次),目前我使用 'redelivered' 标志来实现它。如果不设置'redelivered',我会重新排队消息,否则我会放弃消息。 如果消费者因为尚未处理但 'redelivered' 标志将被设置而崩溃,这将导致那些预取消息(尚未处理)出现问题。
有什么解决办法吗?或者任何其他更好的方法来为 RabbitMQ 消息实现重试逻辑? 谢谢,
我发现此逻辑有几个问题,其中一个您已经指出。首先,redelivered
标志是一个非常无用的字段 - 它为无状态操作提供状态指示(处理消息不需要提供任何 "outside" 信息)。通常,您的消息处理器不应该关心消息是否已传递 1 次、10 次或 100 次 - 消息的处理和相关行为不应取决于传递的次数。
另一个更微妙的问题是,您有几种不同的故障模式,具有不同的影响,并且您发现将所有这些都减少到一个 redelivered
布尔值。
您可以做几件事:
首先,您应该尝试区分由格式错误的消息引起的故障和由服务器的临时情况引起的故障。前者将永远无法被处理(并且应该被彻底拒绝),而后者可能会在条件解决后被处理。现在,您如何在两者之间做出选择?你如何决定在重试之前等待多长时间?
其次,如果您确实需要了解之前的失败,您可以在消息中添加 header 和 re-publish(而不是添加 basic.reject
)。该消息将转到 queue 的后面,但此状态信息现在将成为消息的一部分,可供未来的处理器使用。
如果这是 request-reply 场景,则只需拒绝消息并让客户端重试请求。显然,如果客户端无法知道 when/if 消息已被处理,这是不可取的。
您是否考虑过使用 dead letter exchange?
基本上,您不会将失败的消息重新排队,而是拒绝它。 如果您配置了死信交换,则可以为该被拒绝的消息设置一个新流,例如将其放在您的进程也订阅的另一个队列中。
有了这样的机制,所有的消息都会至少被处理两次,这似乎是你的目标。