我试图在高层次上理解线程分配如何在spring集成流程中发生,特别是在使用aggreagtor时。为了提供一些上下文,我的流程看起来像这样
从目录轮询文件
使用执行程序通道接收轮询文件
聚合轮询文件,直到满足某些标准为止
将聚合文件发布到后续通道,该通道处理所有聚合文件
拆分文件
归档单个文件
此配置的主要目标是将轮询过程与流程中的后续步骤分离。我希望能够在处理现有文件时继续轮询和加载文件。所有这一切都可以正常使用执行程序通道,但一旦达到线程池限制,如果让我们说轮询器线程因CALLER_RUNS拒绝策略而最终被卡住,那么我必须等到这个线程完成才能返回轮询更多文件。
好的,回到我真正的问题,即了解如何在这样的流程中分配线程。因此,poller将文件撤消,将其传递给使用调度程序的执行程序通道,从而创建一个新线程来处理传入文件。现在,一旦这个文件卡在聚合器中,这个线程会发生什么。线程是否已完成/已关闭,因为文件已到达其当前的最终目标。
然后一旦达到聚合器限制并且所有文件都被发送到下一个通道,我假设在新的/单个线程中发生,但是当我们使用拆分器时,它然后为每个拆分文件创建一个新线程。这是正确的。
如果这有点令人困惑,我很抱歉。我真的只是更好地理解这个过程,因为我不喜欢这个设置(我的配置)几乎每次流都在聚合器之后的步骤卡住,这是自处理所有聚合文件以来耗时的步骤..它的大部分CALLER_RUNS最终执行耗时的步骤..然后基本上停止轮询过程,直到这个耗时的步骤完成。
我也会发布我的配置xml,但基本上我希望通过更好地理解线程分配过程,我可以稍微调整一下,而不是使聚合文件处理步骤成为瓶颈。
<!-- Poll files from landing zone directory -->
<int-file:inbound-channel-adapter id="files" directory="${lz.dir.${ft}}" filename-regex=".*\.txt$">
<int:poller fixed-delay="3000" max-messages-per-poll="10" />
</int-file:inbound-channel-adapter>
<int:bridge input-channel="files" output-channel="sourceFiles" />
<!-- Dispatch retrieved files -->
<int:channel id="sourceFiles">
<int:dispatcher task-executor="executor" />
</int:channel>
<!-- Move files to source directory -->
<int:service-activator input-channel="sourceFiles"
output-channel="sourceFilesProcessed"
ref="moveToSource"
method="move" />
<int:channel id="sourceFilesProcessed" />
<!-- Aggregate at source -->
<int:aggregator id="filesBuffered"
input-channel="sourceFilesProcessed"
output-channel="stagedFiles"
release-strategy-expression="size() >= 500 and !@moveToStageAndTarget.isRunning()"
correlation-strategy-expression="'mes-group'"
expire-groups-upon-completion="true"
/>
<int:channel id="stagedFiles" />
<!-- Process aggregated source files -->
<int:chain input-channel="stagedFiles">
<!-- Move stage files to target -->
<int:service-activator ref="moveToStageAndTarget" method="move" />
<!-- Split files back into individual file -->
<int:splitter />
<!-- Archice each file -->
<int:service-activator ref="archiveFiles" method="archive" />
</int:chain>
<task:executor id="executor" pool-size="100" queue-capacity="0" rejection-policy="CALLER_RUNS" />
答案 0 :(得分:1)
使用queue-capacity="0"
是不好的。请看一下ThreadPoolTaskExecutor
的JavaDocs。
因此,坚持实际上是SynchronousQueue
建议使用ExecutorChannel
作为<splitter>
的输出,只要它产生多个Messages
,在您的情况下,它们现在都在同一个Thread
内处理{1}}一个接一个。
聚合器不依赖于线程,但需要记住,发布一个Thread
内的一个组,其Message
对{ {1}} release-strategy
。因此,这是另一个案例,为什么你坚持。