在rabbitmq和spring-rabbitmq中的DLX - 拒绝消息的一些注意事项 [英] DLX in rabbitmq and spring-rabbitmq - some considerations of rejecting messages

查看:219
本文介绍了在rabbitmq和spring-rabbitmq中的DLX - 拒绝消息的一些注意事项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我确实读过这个参考: https://www.rabbitmq.com/dlx.html,但它没有解决我的疑虑,即:

如果接受消息没有问题 - spring-rabbitmq 发送确认和everthing没问题, DLX 不知道有什么消息。

I did read this reference: https://www.rabbitmq.com/dlx.html, however it doesn't resolve my doubts, namely:
In case of accepting message there is no problem - spring-rabbitmq send ack and everthing is fine, DLX doesn't know about acked message.

问题是拒绝回答,即抛出 MessageConverterException ?此邮件已删除或移至 DLX

The problem is in case rejecting answer, namely what about throwing MessageConverterException ? This message is removed or moved to DLX?

如果有其他例外情况怎么办?例如 Exception ?它被删除/重新排队/移动到 DLX

And what about in case other exception ? For example Exception ? It is removed/requeued/moved to DLX ?

在回答@Gary之后编辑

我想,在回答@Gary之后,我应该添加更多关于我的详细信息案例和@Gary的答案的一些总结。 @Gary正好抓住了我的用例。

Edit after answer of @Gary
I think, that after answer's @Gary I should add more details about my case and some summary of @Gary's answer. @Gary exactly grasped my use case.

我不想重新排队 - 从不(我害怕循环),但我不想在抛出异常时丢失消息(例如丢失连接到数据库) - 此消息应重新发送到 DLX 。另一方面,消息的转换应该被视为致命错误 - 没有重新排队,没有重新发送到DLX - 只是永久删除消息。 通常,取决于异常要么拒绝(=如果已配置重新发送到DLX),要么接受,永不重新排队。

I wouldn't like requeue - never (I am afraid of looping), but I wouldn't like to lose messages when an exception was thrown (for example lost connection to database) - this message should be resend to DLX. On the other hand, conversion of message should be treated as fatal error - no requeue, no resend to DLX - simply permanent removing message. Generally, in depends on exception either reject (=resend to DLX if configured) or accept, never requeue.

总结一下@Gary提出的方法。

第一:我们可以覆盖 ExceptionHandler 来管理发送nack / ack,这给了我们完全控制。

第二:IMO更简单,解决方法是设置 defaultRequeueRejected = false 并在转换器中抛出 ImmediateAcknowledgeAmqpException 。它使 RabbitMQ 认为答案被接受(与第一个解决方案相同),而且不会调用侦听器。
**结论**:使用
ImmediateAcknowledgeAmqpException ExceptionHandler`例外我们对永久拒绝具有完全控制权消息(在引擎盖下)并重新发送到DLX。

To sum up in a nutshell approach proposed by @Gary.
First: We can override ExceptionHandler to manage of sending nack/ack, which gives to us a full control.
Second: IMO simpler, solution is to set defaultRequeueRejected=false and in converter throw ImmediateAcknowledgeAmqpException. It makes that RabbitMQ think that answer was accepted (the same thing as in case of first solution), moreover listener wouldn't be invoked. **Conclusion**: UsingImmediateAcknowledgeAmqpExceptionorExceptionHandler` exception we have a full control on permanent rejecting message (under hood ack) and resending to DLX.

推荐答案

RabbitMQ对例外情况一无所知。

RabbitMQ knows nothing about the exceptions.

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

When the container catches an exception it calls channel.basicReject(deliveryTag, requeue).

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

If requeue is true, the message is requeued.

默认情况下,除了上面提到的任何异常这里

By default, for any exception other than those mentioned here


osamqp ... MessageConversionException

o.s.amqp...MessageConversionException

osmessaging ... MessageConversionException

o.s.messaging...MessageConversionException

osmessaging ... MethodArgumentNotValidException

o.s.messaging...MethodArgumentNotValidException

osmessaging ... MethodArgumentTypeMismatchException

o.s.messaging...MethodArgumentTypeMismatchException

java.lang.NoSuchMethodException

java.lang.NoSuchMethodException

java.lang .ClassCastException

java.lang.ClassCastException

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

requeue is set to true, so the message is requeued.

对于这些例外,交付被认为是致命的并且消息没有被重新排队,如果配置了它,它将转到DLX / DLQ。

For those exceptions, the delivery is considered fatal and the message is NOT requeued, it will go to a DLX/DLQ if one is configured.

容器有一个标志 defaultRequeueRejected 默认为true;如果你把它设置为 false ;没有异常将被重新排队。

The container has a flag defaultRequeueRejected which is true by default; if you set it to false; no exceptions will be requeued.

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

For application-level exceptions, generally, messages will be requeued. To dynamically reject (and not requeue) a message, make sure there is an AmqpRejectAndDontRequeueException in the cause chain. This instructs the container to not requeue the message, and it will go to the DLX/DLQ (if configured). This behavior is enabled by the defaultRequeueRejected flag mentioned above.

这些都在文档中解释,因为我已经在其他答案中讨论过,您可以通过使用自定义错误处理程序来更改此行为;这也在文档中有解释。

This is all explained in the documentation and, as I have discussed in other answers to you, you can change this behavior by using a custom error handler; that, too, is explained in the documentation.

不可能向DLX / DLQ发送一些例外而不是其他例外; rabbit只有二进制选项,重新排队或不重新排队,对于后者,如果配置了DLX / DLQ,所有这些被拒绝的消息都会转到DLX / DLQ。

It is not possible to send some exceptions to the DLX/DLQ and not others; rabbit only has a binary option, requeue or don't requeue and, for the latter, if a DLX/DLQ is configured all such rejected messages go to the DLX/DLQ.

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

Spring AMQP provides one more exception, ImmediateAcknowledgeAmqpException. If your listener throws this exception, the message will be ack'd as if it was processed successfully (channel.basicAck()). That is the only technique provided by the container, to discard a bad message without sending it to the DLX/DLQ.

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

Of course, your application can drop such messsages itself.

如果你想DLX / DLQ所有业务异常但丢弃转换异常,抛出 AmqpRejectAndDontRequeueException (或设置 defaultRequeueRejected 为false),并从转换器中抛出 ImmediateAcknowledgeAmqpException

If you want to DLX/DLQ all business exceptions but drop conversion exceptions, throw AmqpRejectAndDontRequeueException (or set defaultRequeueRejected to false), and throw ImmediateAcknowledgeAmqpException from your converter.

这篇关于在rabbitmq和spring-rabbitmq中的DLX - 拒绝消息的一些注意事项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆