一尘不染

Rabbitmq和spring-rabbitmq中的DLX-拒绝消息的一些注意事项

spring-boot

我确实阅读了此参考资料:https :
//www.rabbitmq.com/dlx.html,但是它并不能解决我的疑问,即:
在接受消息的情况下没有问题- spring-rabbitmq发送ack并且一切都很好,DLX不是吗?不知道确认的消息。

问题是万一拒绝答案,那该怎么扔MessageConverterException?此消息已删除或移至DLX

如果还有其他例外情况呢?例如Exception?它已被删除/重新排队/移至DLX


我想 在@Gary的答案之后进行编辑,
我认为,在答案的@Gary之后,我应该添加有关我的案例的更多详细信息以及@Gary答案的一些摘要。@Gary完全掌握了我的用例。

我不希望重新排队-永不(我害怕循环),但我不想在抛出异常(例如,失去与数据库的连接)时丢失消息-
该消息应重新发送给DLX。另一方面,消息的转换应视为致命错误-不重新排队,不重新发送到DLX-只是永久删除消息。
通常,在依赖异常的情况下,拒绝(=如果配置,则返回DLX)或接受,从不重新排队。

总结一下@Gary提出的简单方法。
首先 :我们可以覆盖ExceptionHandler发送小节/小节的管理,这给了我们完全的控制权。
其次 :IMO更简单,解决方案是设置defaultRequeueRejected=false
并在转换器中抛出ImmediateAcknowledgeAmqpException。它使得RabbitMQ认为答案已被接受(与第一种解决方案的情况相同),而且不会调用侦听器。
**Conclusion**: UsingInstantAcknowledgeAmqpException
orExceptionHandler`异常,我们可以完全控制永久拒绝消息(处于高级确认状态)并重新发送到DLX。


阅读 674

收藏
2020-05-30

共1个答案

一尘不染

RabbitMQ对异常一无所知。

当容器捕获异常时,它将调用channel.basicReject(deliveryTag, requeue)

如果requeue为true,则重新排队该消息。

默认情况下,除此处提到的例外外

osamqp … MessageConversionException

osmessaging … MessageConversionException

osmessaging … MethodArgumentNotValidException

osmessaging … MethodArgumentTypeMismatchException

java.lang.NoSuchMethodException

java.lang.ClassCastException

requeue 设置为true,因此将消息重新排队。

对于这些例外,认为传递是致命的,并且不重新排队该消息,如果配置了该消息,它将进入DLX / DLQ。

容器有一个defaultRequeueRejected默认为true 的标志;如果设置为false; 没有例外将被重新排队。

对于应用程序级异常,通常,消息将重新排队。要动态拒绝(而不是重新排队)消息,请确保AmqpRejectAndDontRequeueException原因链中有一个。这指示容器不要重新排队该消息,它将转到DLX
/ DLQ(如果已配置)。通过上述defaultRequeueRejected标志启用此行为。

所有这些都在文档中进行了解释,正如我在其他回答中所讨论的那样,您可以使用自定义错误处理程序来更改此行为。文档中也对此进行了说明。

无法向DLX / DLQ发送某些例外,而不能发送其他例外。rabbit仅具有二进制选项,可以重新排队,也可以不重新排队;对于后者,如果配置了DLX /
DLQ,则所有此类拒绝的消息都将进入DLX / DLQ。

Spring
AMQP提供了另一个例外ImmediateAcknowledgeAmqpException。如果您的听众抛出此异常,则该消息将被确认为成功处理(channel.basicAck())。这是容器提供的唯一技术,用于丢弃错误消息而不将其发送到DLX
/ DLQ。

当然,您的应用程序本身可以丢弃此类消息。

如果要对所有业务异常进行DLX /
DLQ,但要放弃转换异常,则抛出AmqpRejectAndDontRequeueException(或设置defaultRequeueRejected为false),然后ImmediateAcknowledgeAmqpException从转换器中抛出。

2020-05-30