Spring integration 使用聚合器时了解线程池

Spring integration 使用聚合器时了解线程池,spring-integration,Spring Integration,我试图从更高的层次理解spring集成流中线程分配是如何发生的,尤其是在使用aggreator时。为了提供一些上下文,我的流程如下所示 从目录轮询文件 使用执行器通道接收轮询文件 聚合轮询的文件,直到满足某些条件 将聚合文件释放到后续通道,该通道处理所有聚合文件 拆分文件 归档单个文件 此配置的主要目标是将轮询过程与流中的后续步骤分离。我希望能够在处理现有文件时继续轮询和加载文件。使用executor通道可以很好地工作,但是一旦达到线程池限制,并且如果说轮询器线程由于CALLER_运行拒绝策略而

我试图从更高的层次理解spring集成流中线程分配是如何发生的,尤其是在使用aggreator时。为了提供一些上下文,我的流程如下所示

从目录轮询文件
使用执行器通道接收轮询文件
聚合轮询的文件,直到满足某些条件
将聚合文件释放到后续通道,该通道处理所有聚合文件
拆分文件
归档单个文件

此配置的主要目标是将轮询过程与流中的后续步骤分离。我希望能够在处理现有文件时继续轮询和加载文件。使用executor通道可以很好地工作,但是一旦达到线程池限制,并且如果说轮询器线程由于CALLER_运行拒绝策略而被卡住,那么我必须等待该线程完成,然后才能返回轮询更多文件

好的,现在回到我真正的问题,那就是理解线程是如何在这样的流中分配的。因此轮询器重定时一个文件,将其传递给执行器通道,执行器通道使用一个分派器,因此创建一个新线程来处理传入的文件。现在,一旦这个文件卡在聚合器中,这个线程会发生什么情况。线程是否已完成/关闭,因为文件已到达其当前最终目标

一旦达到聚合器限制,所有文件都被发送到下一个通道,我假设这发生在一个新的/单个线程中,但当我们使用拆分器时,它会为每个拆分文件创建一个新线程。对吗

如果这有点混乱,我很抱歉。我真的只是稍微了解了一下这个过程,因为我不喜欢这个设置(我的配置),因为几乎每次流在聚合器之后的步骤卡住时,这是一个耗时的步骤,因为它处理所有聚合的文件。。大多数调用方_运行,最终执行耗时的步骤。。然后基本上停止轮询过程,直到完成这个耗时的步骤

我还将发布我的配置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”
    是不好的。请看一下的JavaDocs。 因此,您的粘滞实际上是在
    SynchronousQueue

  • 建议使用
    ExecutorChannel
    作为
    的输出,只要它生成多条
    消息
    ,在您的情况下,现在它们都在同一
    线程中逐个处理

  • 聚合器不依赖于线程,但需要记住,它释放
    线程
    中的一个组,其
    消息
    表示
    释放策略
    。所以,这是另一种情况,为什么你会粘在一起


  • 不确定队列容量会有什么帮助,因为如果我假设将最大池大小更改为50,将队列容量更改为50,那么最终结果将与最大池大小为100相同。对于拆分器来说,这很有意义,但我认为在我的情况下,让一个线程从拆分器按顺序处理所有文件是可以的,因为这一步非常快,我还可以在流程中保留其他进程使用的线程池。另一个建议是将
    聚合器的输出通道更改为
    队列。无论如何,
    SynchronousQueue
    是坏的。它等待
    提供
    ,然后另一个线程将不会通过设置聚合器的输出通道来执行
    ,这将有什么不同/更好的地方。。我的意思是,聚合器(消息集合)只发送一条消息。。只是想了解你的观点。我将尝试更改队列容量以查看其行为。再次感谢:聚合器不依赖于线程,而是在封闭的线程中发送结果。只要它是一个从你的线程池,并没有在下游流偏差,所有的工作将在该线程内完成。但是这里有一个关于同步队列的问题。这就是为什么轮询任务是粘滞的原因抱歉,我说的是拆分器输出通道是执行器,而不是聚合器,但我明白了一般的想法,我会尝试使用队列大小,看看什么效果更好。谢谢