错误处理
如本手册开头的概述中所述,Spring Integration 等面向消息的框架背后的主要动机之一是促进组件之间的松散耦合。消息通道起着重要作用,因为生产者和消费者不必相互了解。然而,这些优点也有一些缺点。在松散耦合的环境中,有些事情变得更加复杂,错误处理就是一个例子。
当向通道发送消息时,最终处理该消息的组件可能会也可能不会在与发送者相同的线程中运行。如果使用简单的默认值DirectChannel
(当<channel>
元素没有<queue>
子元素且没有'task-executor'属性时),消息处理发生在发送初始消息的同一线程中。在这种情况下,如果 anException
被抛出,它可以被发送者捕获(或者如果它是未捕获的,它可能会传播过去发送者RuntimeException
)。这与普通 Java 调用堆栈中的异常抛出操作具有相同的行为。
在调用者线程上运行的消息流可以通过消息网关(请参阅消息网关)或MessagingTemplate
(请参阅 参考资料)调用MessagingTemplate
。在任何一种情况下,默认行为都是向调用者抛出任何异常。对于消息传递网关,有关如何引发异常以及如何配置网关以将错误路由到错误通道的详细信息,请参阅错误处理。当使用 aMessagingTemplate
或直接发送到 aMessageChannel
时,总是会向调用者抛出异常。
当添加异步处理时,事情变得相当复杂。例如,如果“通道”元素确实提供了“队列”子元素(QueueChannel
在 Java 和注释配置中),则处理消息的组件在与发送者不同的线程中运行。使用 an 时也是如此ExecutorChannel
。发件人可能已将其Message
放入频道并转移到其他事情上。通过Exception
使用标准的Exception
投掷技术,无法将邮件直接投回给该发件人。相反,处理异步进程的错误要求错误处理机制也是异步的。
Spring Integration 通过将错误发布到消息通道来支持对其组件的错误处理。具体来说,Exception
成为 Spring Integration 的有效负载ErrorMessage
。Message
然后将其发送到以类似于“replyChannel”解析的方式解析的消息通道。首先,如果在发生Message
时正在处理的请求Exception
包含“errorChannel”标头(标头名称在MessageHeaders.ERROR_CHANNEL
常量中定义),则将ErrorMessage
其发送到该通道。否则,错误处理程序将发送到 bean 名称为的“全局”通道errorChannel
(这也定义为常量:)IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME
。
默认errorChannel
bean 由框架内部创建。但是,如果您想控制设置,您可以定义自己的。以下示例显示如何在 XML 配置中定义由容量为 的队列支持的错误通道500
:
@Bean
QueueChannel errorChannel() {
return new QueueChannel(500);
}
<int:channel id="errorChannel">
<int:queue capacity="500"/>
</int:channel>
默认错误通道是PublishSubscribeChannel .
|
这里要理解的最重要的事情是,基于消息传递的错误处理仅适用于在TaskExecutor
. 这不适用于由与发送者在同一线程中运行的处理程序引发的异常(例如,通过DirectChannel
本节前面所述的 a )。
当计划轮询任务的执行中发生异常时,这些异常将被包装在ErrorMessage 实例中并发送到“errorChannel”。这是通过MessagePublishingErrorHandler 注入全局taskScheduler bean 来完成的。如果仍然必须使用标准的“errorChannel”集成流逻辑来完成错误处理,建议将其MessagePublishingErrorHandler 用于任何自定义。在这种情况下可以使用
taskScheduler 已注册的bean。integrationMessagePublishingErrorHandler |
要启用全局错误处理,请在该通道上注册一个处理程序。例如,您可以将 Spring Integration 配置ErrorMessageExceptionTypeRouter
为订阅“errorChannel”的端点的处理程序。然后,该路由器可以根据Exception
类型将错误消息传播到多个通道。
Starting with version 4.3.10, Spring Integration provides the ErrorMessagePublisher
and the ErrorMessageStrategy
.
You can use them as a general mechanism for publishing ErrorMessage
instances.
You can call or extend them in any error handling scenarios.
The ErrorMessageSendingRecoverer
extends this class as a RecoveryCallback
implementation that can be used with retry, such as the
RequestHandlerRetryAdvice
.
The ErrorMessageStrategy
is used to build an ErrorMessage
based on the provided exception and an AttributeAccessor
context.
It can be injected into any MessageProducerSupport
or MessagingGatewaySupport
.
The requestMessage
is stored under ErrorMessageUtils.INPUT_MESSAGE_CONTEXT_KEY
in the AttributeAccessor
context.
The ErrorMessageStrategy
can use that requestMessage
as the originalMessage
property of the ErrorMessage
it creates.
The DefaultErrorMessageStrategy
does exactly that.
Starting with version 5.2, all the MessageHandlingException
instances thrown by the framework components, includes a component BeanDefinition
resource and source to determine a configuration point form the exception.
In case of XML configuration, a resource is an XML file path and source an XML tag with its id
attribute.
With Java & Annotation configuration, a resource is a @Configuration
class and source is a @Bean
method.
In most case the target integration flow solution is based on the out-of-the-box components and their configuration options.
When an exception happens at runtime, there is no any end-user code involved in stack trace because an execution is against beans, not their configuration.
Including a resource and source of the bean definition helps to determine possible configuration mistakes and provides better developer experience.
从版本 5.4.3 开始,默认错误通道配置为requireSubscribers = true
在该通道上没有订阅者时(例如,当应用程序上下文停止时)不会静默忽略消息。在这种情况下,aMessageDispatchingException
被抛出,它可能借给入站通道适配器的客户端回调以否定确认(或回滚)源系统中的原始消息,以便重新传递或其他未来考虑。要恢复之前的行为(忽略未发送的错误消息),全局集成属性spring.integration.channels.error.requireSubscribers
必须设置为false
。有关详细信息,请参阅全局属性和PublishSubscribeChannel
配置(如果您errorChannel
手动配置全局)。