配置任务调度器
在 Spring Integration 中,ApplicationContext
扮演着消息总线的核心角色,你只需要考虑几个配置选项。
首先,你可能希望控制中央 TaskScheduler
实例。
你可以通过提供一个名为 taskScheduler
的单例 bean 来实现。
这也被定义为一个常量,如下所示:
IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME
默认情况下,Spring Integration 依赖于 ThreadPoolTaskScheduler
的实例,如 Spring Framework 参考手册的 任务执行和调度 部分所述。
该默认 TaskScheduler
会自动启动,并拥有十个线程的线程池,但请参阅 全局属性。
如果你提供自己的 TaskScheduler
实例,则可以将“autoStartup”属性设置为 false
,或者提供你自己的线程池大小值。
当轮询消费者在其配置中提供显式任务执行器引用时,处理程序方法的调用会在该执行器的线程池中发生,而不是在主调度器池中。 然而,当没有为端点的轮询器提供任务执行器时,它会由主调度器的一个线程调用。
不要在轮询器线程上运行长时间任务。
请改用任务执行器。
如果你有许多轮询端点,可能会导致线程饥饿,除非你增加线程池大小。
此外,轮询消费者默认的 receiveTimeout
为一秒。
由于轮询器线程会阻塞这段时间,我们建议当存在许多此类端点时使用任务执行器,同样是为了避免饥饿。
或者,你可以减少 receiveTimeout
。
如果一个端点的输入通道是基于队列的(即,可轮询的)通道,那么它就是一个轮询消费者。 事件驱动型消费者是指其输入通道具有调度器而不是队列(换句话说,它们是可订阅的)的消费者。 此类端点没有轮询器配置,因为它们的处理程序是直接调用的。 |
在 JEE 容器中运行时,你可能需要使用 Spring 的 TimerManagerTaskScheduler
,如 此处 所述,而不是默认的 taskScheduler
。
为此,请为你的环境定义一个具有相应 JNDI 名称的 bean,如下例所示:
<bean id="taskScheduler" class="org.springframework.scheduling.concurrent.DefaultManagedTaskScheduler">
<property name="jndiName" value="tm/MyTimerManager" />
<property name="resourceRef" value="true" />
</bean>
当在应用程序上下文中配置自定义 TaskScheduler
时(例如上面提到的 DefaultManagedTaskScheduler
),建议为其提供一个 MessagePublishingErrorHandler
(integrationMessagePublishingErrorHandler
bean),以便能够将异常作为发送到错误通道的 ErrorMessage`s 进行处理,就像框架提供的默认 `TaskScheduler
bean 所做的那样。
另请参阅 错误处理 以获取更多信息。