此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring AMQP 3.2.0! |
异常处理
使用 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()
method 返回true
,错误处理程序会抛出AmqpRejectAndDontRequeueException
.
默认的FatalExceptionStrategy
在确定异常为致命异常时记录警告消息。
从 1.6.3 版本开始,将 user exceptions 添加到 fatal list 的一种便捷方法是 subclassConditionalRejectingErrorHandler.DefaultExceptionStrategy
并覆盖isUserCauseFatal(Throwable cause)
method 返回true
对于致命异常。
处理 DLQ 消息的常见模式是将time-to-live
以及其他 DLQ 配置,以便这些消息过期并路由回主队列进行重试。
这种技术的问题在于,导致致命异常的消息会永远循环。
从版本 2.1 开始,ConditionalRejectingErrorHandler
检测到x-death
header 导致引发致命异常的消息。
该消息将被记录并丢弃。
您可以通过设置discardFatalsWithXDeath
属性ConditionalRejectingErrorHandler
自false
.
从版本 2.1.9 开始,默认情况下,具有这些致命异常的消息将被拒绝并且不会重新排队,即使容器确认模式为 MANUAL。
这些异常通常发生在调用侦听器之前,因此侦听器没有机会对消息进行 ack 或 nack,因此它以 un-acked 状态保留在队列中。
要恢复到之前的行为,请将rejectManual 属性ConditionalRejectingErrorHandler 自false . |