异常处理
使用 RabbitMQ Java 客户端的许多操作可能会引发检查异常。
例如,在很多情况下可能会引发实例。
, , 和其他 Spring AMQP 组件捕获这些异常,并将它们转换为层次结构中的异常之一。
这些是在'org.springframework.amqp'包中定义的,并且是层次结构的基础。IOException
RabbitTemplate
SimpleMessageListenerContainer
AmqpException
AmqpException
当侦听器引发异常时,它被包装在 .
通常,消息会被拒绝并被代理重新排队。
设置为 会导致消息被丢弃(或路由到死信交换)。
正如消息侦听器和异步情况中所述,侦听器可以抛出 (or ) 来有条件地控制此行为。ListenerExecutionFailedException
defaultRequeueRejected
false
AmqpRejectAndDontRequeueException
ImmediateRequeueAmqpException
但是,有一类错误是侦听器无法控制行为的。
当遇到无法转换的消息(例如,无效的 header)时,会在消息到达用户代码之前引发一些异常。
设置为 (default) (或throwing an )后,此类消息将一遍又一遍地重新传递。
在版本 1.3.2 之前,用户需要编写自定义 ,如 异常处理 中所述,以避免这种情况。content_encoding
defaultRequeueRejected
true
ImmediateRequeueAmqpException
ErrorHandler
从版本 1.3.2 开始,现在的默认值是 a,它拒绝(并且不会重新排队)因不可恢复的错误而失败的消息。
具体而言,它会拒绝失败并显示以下错误的消息: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 版本中添加。
你可以使用 a 配置此错误处理程序的实例,以便用户可以为条件消息拒绝提供自己的规则 - 例如,从 Spring 重试(消息侦听器和异步情况)的委托实现。
此外,现在还有一个可在决策中使用的属性。
如果该方法返回 ,则错误处理程序将引发 .
默认情况下,当异常被确定为致命异常时,将记录一条警告消息。FatalExceptionStrategy
BinaryExceptionClassifier
ListenerExecutionFailedException
failedMessage
FatalExceptionStrategy.isFatal()
true
AmqpRejectAndDontRequeueException
FatalExceptionStrategy
从版本 1.6.3 开始,将用户异常添加到致命列表的一种便捷方法是 subclass 并覆盖该方法以返回致命异常。ConditionalRejectingErrorHandler.DefaultExceptionStrategy
isUserCauseFatal(Throwable cause)
true
处理 DLQ 消息的常见模式是在这些消息上设置 a 以及其他 DLQ 配置,以便这些消息过期并路由回主队列进行重试。
这种技术的问题在于,导致致命异常的消息会永远循环。
从版本 2.1 开始,它会在消息上检测到导致引发致命异常的 Headers。
该消息将被记录并丢弃。
您可以通过将 上的属性设置为 来恢复到以前的行为。time-to-live
ConditionalRejectingErrorHandler
x-death
discardFatalsWithXDeath
ConditionalRejectingErrorHandler
false
从版本 2.1.9 开始,默认情况下,具有这些致命异常的消息将被拒绝并且不会重新排队,即使容器确认模式为 MANUAL。
这些异常通常发生在调用侦听器之前,因此侦听器没有机会对消息进行 ack 或 nack,因此它以 un-acked 状态保留在队列中。
要恢复到以前的行为,请将 上的属性设置为 。rejectManual ConditionalRejectingErrorHandler false |