Error Handling
如本手册最开始 overview 所述,Spring 集成等面向消息的框架背后的一个主要动机是促进组件之间的松散耦合。消息信道扮演着重要角色,因为生产者和消费者不必互相了解。但是,这些优点也有一些缺点。在松散耦合的环境中,某些事情会变得更加复杂,错误处理就是其中一个示例。
向通道发送消息时,最终处理该消息的组件可能与发送者在同一线程内运行,也可能不在同一线程内运行。如果使用简单的默认 DirectChannel
(其中 <channel>
元素没有 <queue>
子元素,也没有 task-executor
属性),则消息处理发生在发送初始消息的同一线程中。在这种情况下,如果抛出一个 Exception
,它可以被发送者捕获,或者如果它是一个未捕获的 RuntimeException
,则它可能传播到发送者之外。这与正常 Java 调用堆栈中抛出异常的操作相同。
通过消息网关(参见 Messaging Gateways)或 MessagingTemplate
(参见 MessagingTemplate
)可以调用在调用方线程中运行的消息流。在任一情况下,默认行为是向调用方抛出任何异常。对于消息网关,请参阅 Error Handling,了解有关如何抛出异常以及如何配置该网关以将错误路由到错误信道的信息。在使用 MessagingTemplate
或直接发送到 MessageChannel
时,异常始终会抛给调用方。
添加异步处理后,事情变得更加复杂。例如,如果 channel
元素确实提供了一个 queue
子元素(Java 和注释配置中的 QueueChannel
),那么处理消息的组件在与发送器不同的线程中运行。使用 ExecutorChannel
时也是如此。发送者可能已将 Message
放入通道并转到其他事情。Exception
无法使用标准 Exception
抛出技术直接抛回该发送者。相反,处理异步进程的错误要求错误处理机制也是异步的。
Spring Integration 通过将错误发布到消息通道来支持对其组件的错误处理。具体来说,Exception
成为 Spring Integration ErrorMessage
的有效负载。然后将 Message
发送到以类似于 replyChannel
解析的方式解析的消息通道。首先,如果在发生 Exception
时正在处理的请求 Message
具有 errorChannel
标头(标头名称在 MessageHeaders.ERROR_CHANNEL
常量中定义),则 ErrorMessage
将发送到该通道。否则,错误处理程序将发送到 bean 名称为 errorChannel
的“全局”通道(这也定义为一个常量:IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME
)。
框架在内部创建一个默认的 errorChannel
bean。然而,如果你希望控制设置,你可以定义你自己的 errorChannel
。以下示例显示如何在由具有容量为 500
的队列做后盾的 XML 配置中定义错误通道:
-
Java
-
XML
@Bean
QueueChannel errorChannel() {
return new QueueChannel(500);
}
<int:channel id="errorChannel">
<int:queue capacity="500"/>
</int:channel>
默认的错误通道是 |
这里要理解的最重要的事情是,基于消息的错误处理仅适用于由在 TaskExecutor
内执行的 Spring Integration 任务抛出的异常。这并不适用于在与发送者同一线程内操作的处理程序抛出的异常(例如,如本节前面所述,通过 DirectChannel
)。
当计划的轮询任务执行中发生异常时,这些异常会封装在 |
要启用全局错误处理,请在该通道上注册一个处理程序。例如,你可以将 Spring Integration 的 ErrorMessageExceptionTypeRouter
配置为订阅 errorChannel
的端点的处理程序。然后,根据 Exception
类型,该路由器可以将错误消息分散到多个通道。
从版本 4.3.10 开始,Spring 集成提供 ErrorMessagePublisher
和 ErrorMessageStrategy
。您可以将它们用作发布 ErrorMessage
实例的一般机制。您可以在任何错误处理场景中调用或扩展它们。ErrorMessageSendingRecoverer
将此类扩展为可用于重试的 RecoveryCallback
实现,例如 RequestHandlerRetryAdvice
。ErrorMessageStrategy
用于根据提供的异常和 AttributeAccessor
上下文构建 ErrorMessage
。它可以注入到任何 MessageProducerSupport
或 MessagingGatewaySupport
中。requestMessage
储存在 AttributeAccessor
上下文中的 ErrorMessageUtils.INPUT_MESSAGE_CONTEXT_KEY
下。ErrorMessageStrategy
可以使用该 requestMessage
作为其创建的 ErrorMessage
的 originalMessage
属性。DefaultErrorMessageStrategy
正好就是这样做的。
从 5.2 版开始,框架组件抛出的所有 MessageHandlingException
实例都包含一个组件 BeanDefinition
资源和源来确定配置点以形成异常。在 XML 配置中,资源是 XML 文件路径和带其 id
属性的 XML 标记。在使用 Java 和注释的配置中,资源是一个 @Configuration
类和源是一个 @Bean
方法。在大多数情况下,目标集成流程解决方案基于开箱即用的组件及其配置选项。当在运行时发生异常时,由于执行针对 bean,而不是 bean 的配置,因此堆栈跟踪中不包含任何最终用户代码。包含 bean 定义的资源和源有助于确定可能的配置错误,并提供更好的开发人员体验。
从版本 5.4.3 开始,默认错误信道配置了属性 requireSubscribers = true
,以便在该信道上没有订阅者时不静默忽略消息(例如,当应用程序上下文已停止时)。在这种情况下,将抛出一个 MessageDispatchingException
,该异常可能会借用入站信道适配器的客户端回调函数,以否定确认(或回滚)源系统中的原始消息,以便重新传递或将来考虑。要恢复之前的行为(忽略未分派错误消息),则必须将全局集成属性 spring.integration.channels.error.requireSubscribers
设置为 false
。有关详细信息,请参见 Global Properties 和 PublishSubscribeChannel
Configuration(如果您手动配置全局 errorChannel
)。
另请参阅 Error Handling Sample 了解更多信息。