Spring Integration中XLS Service Activator被任务执行器池执行的原因排查
首先咱们来拆解下问题根源:你的XLS生成器之所以会跑到sqlGathererExecutor或webGathererExecutor线程里执行,是Spring Integration的线程传播特性在起作用——当Aggregator完成聚合逻辑时,它是在触发它的上游线程(也就是来自两个Gatherer Executor池的线程)上执行的,后续的Router和XLS生成器Service Activator会直接复用这个线程继续处理,自然就会显示在之前的Executor池线程中运行。
让XLS生成器独立运行的两种方案
方案1:给XLS处理链配置专属线程池
修改XLS相关的通道和链配置,为它单独设置队列通道和Executor:
<!-- 配置独立的队列通道 --> <int:channel id="XLS-channel"> <int:queue capacity="10"/> </int:channel> <!-- 定义XLS生成器专属的Task Executor --> <task:executor id="xlsGeneratorExecutor" pool-size="5" queue-capacity="10"/> <!-- 为XLS处理链配置专属Poller,绑定自定义Executor --> <int:chain input-channel="XLS-channel" output-channel="mailSender-channel"> <int:poller task-executor="xlsGeneratorExecutor" fixed-delay="100"/> <int:service-activator ref="xlsGenerator" method="generate"/> </int:chain>
将XLS-channel改为队列通道后,消息会被暂存,再由绑定了专属xlsGeneratorExecutor的Poller拉取处理,彻底和上游的Gatherer线程池隔离。
方案2:在Aggregator后插入Executor Channel切换线程
另一种更简洁的方式是在Aggregator和Router之间新增一个Executor Channel,强制切换线程:
<!-- 新增用于线程切换的Executor Channel --> <int:channel id="aggregator-router-switch-channel"> <int:dispatcher task-executor="xlsGeneratorExecutor"/> </int:channel> <!-- 修改原链的输入通道为新增的切换通道 --> <int:chain input-channel="aggregator-router-switch-channel"> <int:router ref="generatorRouter" method="route"/> </int:chain> <!-- 定义XLS生成器专属的Task Executor --> <task:executor id="xlsGeneratorExecutor" pool-size="5" queue-capacity="10"/>
这种方式下,Aggregator输出的消息进入aggregator-router-switch-channel时,会自动提交到xlsGeneratorExecutor的线程池,后续的Router和XLS生成器都会在这个专属线程池中执行。
核心原理
Spring Integration中,默认的Direct Channel会直接复用调用方线程处理消息;而Queue Channel配合Poller、或者Executor Channel,则会触发线程切换,将消息提交到指定的线程池执行,从而实现组件的线程隔离。
内容的提问来源于stack exchange,提问作者Prachit Raorane

