对于最新的稳定版本,请使用 Spring Integration 6.4.0! |
错误处理
正如本手册开头的概述中所述,面向消息的框架(如 Spring Integration)背后的主要动机之一是促进组件之间的松耦合。 消息通道起着重要作用,因为生成者和使用者不必相互了解。 但是,这些优点也有一些缺点。 在松散耦合的环境中,有些事情会变得更加复杂,错误处理就是一个例子。
当向通道发送消息时,最终处理该消息的组件可能与发送者在同一个线程中运行,也可能不在运行。
如果使用简单的默认DirectChannel
(当<channel>
元素中没有<queue>
child 元素,并且没有 'task-executor' 属性),消息处理发生在发送初始消息的同一线程中。
在这种情况下,如果Exception
被抛出,则它可能被发送者捕获,或者如果它是未捕获的RuntimeException
.
这与普通 Java 调用堆栈中的异常引发作的行为相同。
在调用方线程上运行的消息流可以通过消息传递网关(请参阅消息传递网关)或MessagingTemplate
(参见MessagingTemplate
).
在任何一种情况下,默认行为都是向调用方引发任何异常。
对于消息传递网关,请参阅错误处理,了解有关如何引发异常以及如何配置网关以将错误路由到错误通道的详细信息。
当使用MessagingTemplate
或发送到MessageChannel
直接,异常总是抛给调用方。
添加异步处理时,事情会变得更加复杂。
例如,如果 'channel' 元素确实提供了一个 'queue' 子元素 (QueueChannel
在Java和注释配置中),处理消息的组件与发送者在不同的线程中运行。
当ExecutorChannel
被使用。
发件人可能已丢弃Message
进入频道,然后转向其他事情。
没有办法Exception
使用标准Exception
投掷技术。
相反,处理异步进程的错误要求错误处理机制也是异步的。
Spring 集成通过将错误发布到消息通道来支持对其组件进行错误处理。
具体来说,Exception
成为 Spring 集成的有效负载ErrorMessage
.
那Message
然后发送到消息通道,该通道的解析方式类似于 'replyChannel' 解析。
首先,如果请求Message
正在处理Exception
occurred 包含一个 'errorChannel' 标头(标头名称在MessageHeaders.ERROR_CHANNEL
constant)、ErrorMessage
将发送到该通道。
否则,错误处理程序将发送到 Bean 名称为errorChannel
(这也定义为常量:IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME
).
默认的errorChannel
bean 是由 Framework 在内部创建的。
但是,如果要控制设置,您可以定义自己的设置。
以下示例说明如何在 XML 配置中定义错误通道,该配置由容量为500
:
-
Java
-
XML
@Bean
QueueChannel errorChannel() {
return new QueueChannel(500);
}
<int:channel id="errorChannel">
<int:queue capacity="500"/>
</int:channel>
默认的 error 通道是一个PublishSubscribeChannel .
默认情况下,它有一个LoggingHandler 作为具有ERROR logging level 和 subscription order 设置为Ordered.LOWEST_PRECEDENCE - 100 .
如果您订阅其他使用终端节点,这可能会引发异常,并且您不想抢占日志记录,请确保其他处理程序具有更高的顺序。 |
这里要理解的最重要的一点是,基于消息传递的错误处理仅适用于在TaskExecutor
.
这不适用于在与发送者相同的线程中运行的处理程序引发的异常(例如,通过DirectChannel
如本节前面所述)。
当计划的 Poller 任务执行中发生异常时,这些异常将被包装在ErrorMessage 实例,并发送到 'errorChannel' 中。
这是通过MessagePublishingErrorHandler 注入到全局taskScheduler 豆。
建议使用MessagePublishingErrorHandler 适用于任何自定义taskScheduler 如果仍然必须使用标准 'errorChannel' 集成流逻辑完成错误处理。
已注册integrationMessagePublishingErrorHandler 在这种情况下可以使用 bean。 |
要启用全局错误处理,请在该通道上注册处理程序。
例如,您可以配置 Spring Integration 的ErrorMessageExceptionTypeRouter
作为订阅了errorChannel
.
然后,该路由器可以根据Exception
类型。
从版本 4.3.10 开始, Spring 集成提供了ErrorMessagePublisher
和ErrorMessageStrategy
.
您可以将它们用作发布的一般机制ErrorMessage
实例。
您可以在任何错误处理场景中调用或扩展它们。
这ErrorMessageSendingRecoverer
将此类扩展为RecoveryCallback
可与 Retry 一起使用的实现,例如RequestHandlerRetryAdvice
.
这ErrorMessageStrategy
用于构建ErrorMessage
基于提供的异常和AttributeAccessor
上下文。
它可以注射到任何MessageProducerSupport
或MessagingGatewaySupport
.
这requestMessage
存储在ErrorMessageUtils.INPUT_MESSAGE_CONTEXT_KEY
在AttributeAccessor
上下文。
这ErrorMessageStrategy
可以使用那个requestMessage
作为originalMessage
属性的ErrorMessage
它创造。
这DefaultErrorMessageStrategy
确实如此。
从版本 5.2 开始,所有MessageHandlingException
框架组件引发的实例包括一个组件BeanDefinition
resource 和 source 来确定异常中的配置点。
在 XML 配置的情况下,资源是 XML 文件路径,并使用其 XML 标记源 XML 标记id
属性。
使用 Java & Annotation 配置,资源是一个@Configuration
class 和 source 是@Bean
方法。
在大多数情况下,目标集成流解决方案基于开箱即用的组件及其配置选项。
当运行时发生异常时,堆栈跟踪中不涉及任何最终用户代码,因为执行是针对 Bean,而不是它们的配置。
包括 Bean 定义的资源和源有助于确定可能的配置错误,并提供更好的开发人员体验。
从版本 5.4.3 开始,默认 error 通道配置了属性requireSubscribers = true
当此通道上没有订阅者时(例如,当 Application Context 停止时),不静默忽略消息。
在本例中,一个MessageDispatchingException
,这可能会使入站通道适配器的客户端回调对源系统中的原始消息进行否定确认(或回滚),以便重新传递或将来考虑其他消息。
要恢复以前的行为(忽略未调度的错误消息),全局集成属性spring.integration.channels.error.requireSubscribers
必须设置为false
.
请参阅 全局属性 和PublishSubscribeChannel
配置(如果您配置全局errorChannel
manually) 了解更多信息。
有关更多信息,另请参阅 错误处理示例 。