使用 RabbitMQ Java 客户端的许多操作都可能引发选中的异常。
例如,在很多情况下,实例可能会被抛出。
、 和其他 Spring AMQP 组件捕获这些异常,并将它们转换为层次结构中的异常之一。
这些在“org.springframework.amqp”包中定义,是层次结构的基础。IOException
RabbitTemplate
SimpleMessageListenerContainer
AmqpException
AmqpException
当侦听器引发异常时,它会包装在 .
通常,消息被代理拒绝并重新排队。
设置为会导致邮件被丢弃(或路由到死信交换)。
如消息侦听器和异步案例中所述,侦听器可以抛出 (或) 来有条件地控制此行为。ListenerExecutionFailedException
defaultRequeueRejected
false
AmqpRejectAndDontRequeueException
ImmediateRequeueAmqpException
但是,有一类错误,侦听器无法控制行为。
当遇到无法转换的消息(例如,无效的标头)时,会在消息到达用户代码之前引发一些异常。
设置为 (default) (或抛出 ),此类消息将一遍又一遍地重新传递。
在版本 1.3.2 之前,用户需要编写一个自定义 ,如异常处理中所述,以避免这种情况。content_encoding
defaultRequeueRejected
true
ImmediateRequeueAmqpException
ErrorHandler
从版本 1.3.2 开始,默认值现在为拒绝(并且不重新排队)失败并出现不可恢复错误的消息。
具体而言,它拒绝失败并出现以下错误的消息:ErrorHandler
ConditionalRejectingErrorHandler
-
o.s.amqp…MessageConversionException
:在使用 .MessageConverter
-
o.s.messaging…MessageConversionException
:如果在映射到方法时需要其他转换,则可以由转换服务抛出。@RabbitListener
-
o.s.messaging…MethodArgumentNotValidException
:如果在侦听器中使用验证(例如,)并且验证失败,则可以抛出。@Valid
-
o.s.messaging…MethodArgumentTypeMismatchException
:如果入站消息已转换为对目标方法不正确的类型,则可以引发。 例如,参数声明为 but is received。Message<Foo>
Message<Bar>
-
java.lang.NoSuchMethodException
:在 1.6.3 版中添加。 -
java.lang.ClassCastException
:在 1.6.3 版中添加。
您可以使用 来配置此错误处理程序的实例,以便用户可以提供自己的条件消息拒绝规则 — 例如,从 Spring 重试(消息侦听器和异步案例)的委托实现。
此外,now 还有一个属性,您可以在决策中使用该属性。
如果该方法返回 ,则错误处理程序将抛出 .
默认情况下,当异常被确定为致命时,会记录一条警告消息。FatalExceptionStrategy
BinaryExceptionClassifier
ListenerExecutionFailedException
failedMessage
FatalExceptionStrategy.isFatal()
true
AmqpRejectAndDontRequeueException
FatalExceptionStrategy
从版本 1.6.3 开始,将用户异常添加到致命列表的一种便捷方法是子类化并重写该方法以返回致命异常。ConditionalRejectingErrorHandler.DefaultExceptionStrategy
isUserCauseFatal(Throwable cause)
true
处理 DLQ 消息的常见模式是在这些消息以及其他 DLQ 配置上设置 a,以便这些消息过期并路由回主队列进行重试。
这种技术的问题在于,导致致命异常的消息会永远循环。
从版本 2.1 开始,将检测导致引发致命异常的消息上的标头。
消息将被记录并丢弃。
您可以通过将 to 上的属性设置为 来恢复到以前的行为。time-to-live
ConditionalRejectingErrorHandler
x-death
discardFatalsWithXDeath
ConditionalRejectingErrorHandler
false
从版本 2.1.9 开始,默认情况下,具有这些致命异常的消息将被拒绝并且不会重新排队,即使容器确认模式为 MANUAL。
这些异常通常发生在调用侦听器之前,因此侦听器没有机会确认或啃咬消息,因此消息仍处于未确认状态。
若要恢复到上一个行为,请将 上的属性设置为 。rejectManual ConditionalRejectingErrorHandler false |
从版本 2.1.9 开始,默认情况下,具有这些致命异常的消息将被拒绝并且不会重新排队,即使容器确认模式为 MANUAL。
这些异常通常发生在调用侦听器之前,因此侦听器没有机会确认或啃咬消息,因此消息仍处于未确认状态。
若要恢复到上一个行为,请将 上的属性设置为 。rejectManual ConditionalRejectingErrorHandler false |