Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java rabbitmq和spring rabbitmq中的DLX-拒绝消息的一些注意事项_Java_Spring Boot_Rabbitmq_Spring Amqp_Spring Rabbit - Fatal编程技术网

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

Java rabbitmq和spring rabbitmq中的DLX-拒绝消息的一些注意事项,java,spring-boot,rabbitmq,spring-amqp,spring-rabbit,Java,Spring Boot,Rabbitmq,Spring Amqp,Spring Rabbit,我确实读过这篇参考文献:,但它并没有解决我的疑问,即: 在接受消息的情况下没有问题-spring rabbitmqsend ack,一切正常,DLX不知道已确认的消息 问题在于拒绝回答的情况,即抛出MessageConverterException?此消息将被删除或移动到DLX 万一有其他例外呢?例如异常?它被删除/重新查询/移动到DLX 在@Gary回答后编辑 我认为,在回答@Gary之后,我应该添加更多关于我的案例的细节和@Gary回答的一些总结@Gary完全掌握了我的用例 我不喜欢requ

我确实读过这篇参考文献:,但它并没有解决我的疑问,即:
在接受消息的情况下没有问题-
spring rabbitmq
send ack,一切正常,
DLX
不知道已确认的消息

问题在于拒绝回答的情况,即抛出
MessageConverterException
?此消息将被删除或移动到
DLX

万一有其他例外呢?例如
异常
?它被删除/重新查询/移动到
DLX

在@Gary回答后编辑
我认为,在回答@Gary之后,我应该添加更多关于我的案例的细节和@Gary回答的一些总结@Gary完全掌握了我的用例

我不喜欢requeue-从不(我害怕循环),但我不喜欢在抛出异常时丢失消息(例如与数据库的连接丢失)-此消息应重新发送到
DLX
。另一方面,消息转换应被视为致命错误-无需重新请求,无需重新发送到DLX-只是永久删除消息通常情况下,in取决于异常拒绝(=重新发送到DLX,如果已配置)或接受,从不重新请求。

简而言之,@Gary提出的方法。
首先:我们可以覆盖
异常处理程序
来管理发送nack/ack的操作,这给了我们完全的控制权。
第二个:在我看来更简单,解决方案是设置
defaultRequeueRejected=false
并在转换器中抛出
ImmediateAcknowledgeAmqpException
。它使
RabbitMQ
认为答案被接受(与第一个解决方案的情况相同),而且监听器不会被调用<代码>
**结论**:使用ImmediateAcknowledgeAmqpException
ExceptionHandler`exception,我们可以完全控制永久拒绝消息(在hood ack下)和重新发送到DLX

RabbitMQ对异常一无所知

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

如果requeue为true,则消息将被重新查询

默认情况下,除上述情况外的任何例外情况

o、 s.amqp…MessageConversionException

o、 s.messaging…MessageConversionException

o、 美国消息传递…MethodArgumentNotValidException

o、 美国消息传递…MethodArgumentTypeMismatchException

java.lang.NoSuchMethodException

java.lang.ClassCastException

requeue
设置为true,因此消息将被重新查询

对于这些例外情况,传递被认为是致命的,并且消息不会被重新请求,如果配置了DLX/DLQ,它将转到DLX/DLQ

容器有一个默认为true的标志
defaultRequeueRejected
;如果将其设置为
false
;不会重新查询任何例外情况

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

这些都在文档中进行了解释,正如我在其他回答中所讨论的,您可以通过使用自定义错误处理程序来更改此行为;文档中也解释了这一点

无法向DLX/DLQ发送某些异常,而不能发送其他异常;rabbit只有一个二进制选项requeue或don't requeue,对于后者,如果配置了DLX/DLQ,则所有这些被拒绝的消息都会转到DLX/DLQ

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

当然,您的应用程序本身也可以删除这些消息


如果要DLX/DLQ所有业务异常,但要删除转换异常,请从转换器中抛出
amqprejected和dontrequeueexception
(或将
defaultRequeueRejected
设置为false),并立即抛出
KnowledgeAmqpeption

谢谢您的明确回答。我编辑我的帖子是为了澄清这个问题并总结你们的想法。什么方法(
ExceptionHandler
ImmediateAcknowledgeAmqpException
应该使用?IMO
ImmediateAcknowledgeAmqpException
,因为它更简单,并提供完全控制。这是您的选择;对于自定义转换器,在那里执行此操作可能更容易/更简单,并使用标准错误处理程序。如果您希望使用其他converters也一样,并且想要相同的行为,自定义错误处理程序可能更好。但您在编辑中的分析是正确的。当涉及到
ErrorHandler
-应该覆盖哪些函数(请记住DLX已配置)?我认为
isFatal
在这方面会有所帮助。我们应该设置
defaultRequeueRejected=false
来整体阻止重新查询。然后,从
isFatal
返回true,我们确保消息不会被重新发送到
DLX
,只需永久删除。当我们从
isFatal
false返回时,它将自动被删除esend to
DLX
。是吗?我建议您使用自定义的
ErrorHandler
,而不是试图使
ConditionalRejectingErrorHandler
满足您的需要-它仅用于分析异常以确定是否应重新查询消息。您需要其他功能-决定是否使用异常后的消息,或者不是。一个简单的
错误