错误处理

如本手册开头的概述中所述,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 的有效负载ErrorMessageMessage然后将其发送到以类似于“replyChannel”解析的方式解析的消息通道。首先,如果在发生Message时正在处理的请求Exception包含“errorChannel”标头(标头名称在MessageHeaders.ERROR_CHANNEL常量中定义),则将ErrorMessage其发送到该通道。否则,错误处理程序将发送到 bean 名称为的“全局”通道errorChannel(这也定义为常量:)IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME

默认errorChannelbean 由框架内部创建。但是,如果您想控制设置,您可以定义自己的。以下示例显示如何在 XML 配置中定义由容量为 的队列支持的错误通道500

java
@Bean
QueueChannel errorChannel() {
    return new QueueChannel(500);
}
XML
<int:channel id="errorChannel">
    <int:queue capacity="500"/>
</int:channel>
默认错误通道是PublishSubscribeChannel.

这里要理解的最重要的事情是,基于消息传递的错误处理仅适用于在TaskExecutor. 这不适用于由与发送者在同一线程中运行的处理程序引发的异常(例如,通过DirectChannel本节前面所述的 a )。

当计划轮询任务的执行中发生异常时,这些异常将被包装在ErrorMessage实例中并发送到“errorChannel”。这是通过MessagePublishingErrorHandler注入全局taskSchedulerbean 来完成的。如果仍然必须使用标准的“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手动配置全局)。


1. see XML Configuration