仅聚合具有相同关联键的连续交换

时间:2016-11-11 10:38:42

标签: stream apache-camel aggregator

我正在使用Apache Camel并获取一个大文件用于输入,我必须逐行处理。内容已经排序,我必须使用相同的相关键聚合所有连续的行。如果相关键发生更改,则必须完成先前的聚合。如果文件结束,那么最后的聚合也已完成。 我有一些限制: - 因为传入的文件相当大,我们希望以流式方式处理它。 - 因为结果是给同步端点的,所以我不想使用超时完成谓词。否则我将失去调节数据源消耗速度的背压,交换将累积在AggregateProcessor的超时映射和聚合存储库中。

PreCompletionAwareAggregationStrategy看起来是一个很有前途的解决方案但事实证明,在下一个文件到达之前,最后的聚合将不会完成。如果我在preComplete中使用CamelSplitComplete属性,则最后一个聚合完成但没有最后一个传入交换。相反,最后一次交换将被添加到下一个文件的内容中。

所以目前我很难找到一个并不过分丑陋的解决方案。

2 个答案:

答案 0 :(得分:0)

好吧,也许有一种方法可能是因为您的数据已经排序是以流方式解析并将具有相同关联键的每一行添加到某个hashmap结构。一旦遇到新的相关键,您基本上想要“刷新”散列映射以创建新消息,然后重新启动相同的过程。看看这里: http://camel.apache.org/how-do-i-write-a-custom-processor-which-sends-multiple-messages.html

答案 1 :(得分:0)

在所描述的场景中,我将分裂的消息发送到带有聚合器的路由(让我们称之为“AggregationRoute”),其聚合策略实现了PreCompletionAwareAggregationStrategy(我猜你已经在使用它的方式)。 然后,当拆分结束时,将AGGREGATION_COMPLETE_ALL_GROUPS标头设置为true并将其发送到AggregationRoute。此交换仅用作完成所有聚合组的信号。

示例:


    ...
    .split(body()).streaming()
        .to("direct:aggregationRoute")
    .end()
    .setHeader(Exchange.AGGREGATION_COMPLETE_ALL_GROUPS,constant(true))
    .to("direct:aggregationRoute");

from("direct:aggregationRoute")
    .aggregate([your correlation expression]), myAggregationStrategy)
    ...

另一种方法是使用AggregateController通过调用其方法forceCompletionOfAllGroups()结束所有组的聚合:


AggregateController aggregateController = new DefaultAggregateController();

from(...)
    ...
    .split(body()).streaming()
        .aggregate([correlation expression], aggregationStrategy).aggregateController(aggregateController)
            ...
            // Do what you need to do with the aggregated exchange
            ...
        .end()
    .end()
    .bean(aggregateController, "forceCompletionOfAllGroups")