Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从聚合器发布两次spring集成消息_Spring_Spring Integration - Fatal编程技术网

从聚合器发布两次spring集成消息

从聚合器发布两次spring集成消息,spring,spring-integration,Spring,Spring Integration,我有一个spring集成流,它从一个channel inboundadapter开始,拾取文件并将它们作为消息传递给系统。 在几个组件之后,消息在一个“聚合器”中聚合,根据释放策略或30秒的组超时从该聚合器中释放消息。 下游处理有另一组组件,直到最后一组 我面临的问题是, 当我发送33个文件时,这些文件根据相关ID创建了33个“组/桶”,并在“聚合器”中聚合,其中一些文件或消息似乎被“释放”了两次。我之所以得出这样的结论是因为我有一个通道拦截器,它显示了一些消息在第一次成功完成下游处理后第二次通

我有一个spring集成流,它从一个channel inboundadapter开始,拾取文件并将它们作为消息传递给系统。 在几个组件之后,消息在一个“聚合器”中聚合,根据释放策略或30秒的组超时从该聚合器中释放消息。 下游处理有另一组组件,直到最后一组

我面临的问题是, 当我发送33个文件时,这些文件根据相关ID创建了33个“组/桶”,并在“聚合器”中聚合,其中一些文件或消息似乎被“释放”了两次。我之所以得出这样的结论是因为我有一个通道拦截器,它显示了一些消息在第一次成功完成下游处理后第二次通过“已发布”通道(出现在聚合器之后)。此外,此行为会导致我的应用程序找不到文件并引发我看到的异常。这让我得出结论,消息bucket/group/corrID不知何故被“释放”了两次

我尝试了很多方法来调试它,但本质上,我想知道一个corrID/bucket在被释放并在一个线程中成功地通过了所有下游组件之后,如何再次“释放”

我的问题是,如何调试它?我想知道是什么使此消息/存储桶重新出现在聚合器中。 我的聚合器如下所示

<int:aggregator id="bufferedFiles" input-channel="inQueueForStage"
        output-channel="released" expire-groups-upon-completion="true"
        send-partial-result-on-expiry="true" release-strategy="releaseHandler"
        release-strategy-method="canRelease"
        group-timeout-expression="size() > 0 ? T(com.att.datalake.ifr.loader.utils.MessageUtils).getAggregatorTimeout(one, @sourceSnapshot) : -1">
        <int:poller fixed-delay="${files.pickup.delay:3000}"
            max-messages-per-poll="${num.files.pickup.per.poll:10}"
            task-executor="executor" />
    </int:aggregator>

聚合器的说明:size()>0适用于每个关联桶。由于文件名的原因,我发送的33个文件中的每一个都将产生/生成/创建一个新的bucket,因此聚合器将有33个bucket/groups/corrIds,每个bucket将只包含一个文件。 因此聚合器SPEL表达式只是说,如果没有发布策略,那么在30秒后释放bucket/组(如果组确实至少有一些文件)

我的通道入站适配器如下所示:


日志 这是第一次完成流的消息日志。调用的完成时间表示到达最后一个组件“completionHandler”SA。

日志解释:“cor”是两次释放的bucket/corrId。我得到最后一个异常的原因是,第一次从原始位置删除文件并进行处理。因此,第二次发生这种错误的释放时,没有什么可处理的。 从图中可以看出,第一批/corrId/bucket在11:09左右加工完成,第二批在11:10左右开始

重要的一点我注意到,这种行为只有在我有一个全局通道拦截器时才会发生,在该拦截器中我正在进行一些长时间的处理。当这个拦截器被注释掉时,错误就会消失

问题: 聚合器是否可以在任何情况下双重发布批次/勘误表?如何使聚合器发出任何日志

谢谢

编辑晚上10:15

我在聚合器后面的频道有一个拦截器,如下所示

<int:aggregator id="bufferedFiles" input-channel="inQueueForStage"
        output-channel="released" expire-groups-upon-completion="true"
        send-partial-result-on-expiry="true" release-strategy="releaseHandler"
        release-strategy-method="canRelease"
        group-timeout-expression="size() > 0 ? T(com.att.datalake.ifr.loader.utils.MessageUtils).getAggregatorTimeout(one, @sourceSnapshot) : -1">
        <int:poller fixed-delay="${files.pickup.delay:3000}"
            max-messages-per-poll="${num.files.pickup.per.poll:10}"
            task-executor="executor" />
    </int:aggregator>
公共消息呈现(消息消息、消息频道){
LOGGER.info(“*******从聚合器(拦截器)中释放),corrID:{}at time:{}*******”,MessageUtils.getCorrelationId(message),new Date());
finalReporter.callback(channel.toString(),message);
返回消息;
}

从聚合器到最终CompetitionHandler SA,我有单线程处理 聚合器->发布频道->某些SA1->某些频道->…->completionChannel->completeSA

当我运行33个分区时,让我们按照第一次发布的corrId=“alh”进行操作,如下所示:, 它显示的是线程5释放了它,它应该处理所有下游组件。但它中途离开,开始做其他事情,稍后由不同的线程再次拾取,如下所示, 这似乎是个问题

解决方案更新: 我做了以下三件事来解决这个问题

  • 出于某种原因,我的拦截器正在执行
    returnsuper.preSend(message,channel)
    而不是简单地执行
    returnmessage
    。我改成了后者

  • 我有一个全球频道拦截器,我删除了全球频道拦截器,保留了单个频道拦截器

  • 如果通道拦截器在返回之前出现任何问题,是否会导致新版本的发布

  • 尽管我仍然可以在图片中看到上面描述的场景,但我没有得到双重处理尝试,因此避免了错误。我仍在试图弄明白这一点


    我知道这太具体了,很难解释;仍然感谢您的时间和评论…

    但是,是的。我认为@GaryRussell是正确的:因为您使用了
    在完成时过期组=“true”
    一些部分组可能会通过
    组超时表达式释放,并且具有相同
    相关ID的新消息将形成一个新组,在下一次
    组超时时释放。你的
    size()>0
    也不好。这意味着它将在组超时后释放部分组。可能是
    size()>1
    ?但组不能为
    size()==0
    。因为它是在第一条消息上创建的,所以,如果GROUP存在,它至少包含一条消息。是的,组可以为空,但在这种情况下,聚合器应标记为
    在完成时过期组=“false”
    。在这种情况下,它被标记为
    已完成
    ,并且不允许新消息。

    在与调试和各种盲场景进行斗争后,我相信至少我有一个解决方法和可能的根本原因。我将尝试概述我修改的所有内容

    根C