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