消息聚合的Camel条件

时间:2013-12-16 11:17:43

标签: apache-camel aggregation

我正在寻找一种基于消息聚合来有条件地处理消息的方法。我已经研究了很多方法,但似乎Apache Camel不支持它。我将解释这个场景,然后解释我尝试的解决方案。

方案: 我正在尝试有条件地清理目录。我每隔x天从目录轮询并获取所有文件(file:// ...)。我将其路由到聚合,聚合将文件聚合为单个大小(directorySize)。然后我检查这个大小是否超过了某个阈值。

这就是问题所在。我现在想要删除某些文件,如果这个条件通过,但我不再访问原始邮件,因为它们是在新的交换中聚合的。

解决方案:

  • 我试图再次获取文件来处理它们。问题是,就我所知,你无法按需获取消费者。我尝试使用pollEnrich,但这只会获取单个文件而不是目录中的所有文件。
  • 我试图过滤/停止父路线。这里的问题是filter()/ choice ... stop()/ end()只会停止带有目录大小的聚合路由,而不会停止带有文件消息的父路由。我不能有条件地处理这些。
  • 我试图将聚合条件移动到我要调用的另一条路径,但这会导致与第一个解决方案相同的问题。

我认为的事情:

  • 重写聚合策略,不仅要将大小聚合,还要将文件本身聚合到distributedExchange中。这样我可以在检查后再次拆分聚合。我真的不喜欢这个解决方案,因为它在代码中和运行时都会产生很多样板。
  • 将文件大小计算器移动到处理器而不是聚合器。这将首先打败使用骆驼的目的..我会手动获取文件并添加大小..而且每个文件都有...
  • 使用ControlBus动态启动该目录上的删除路由。再一次尝试实现我认为应该能够以简单的方式完成的工作。
  • 我想在每条父消息上设置计算出的大小,但我不知道如何实现这一目标?
  • 另一种停止我没想过的父路线的方法是什么?

我有点震惊,你不能根据这些消息的聚合优雅地过滤消息。我在Camel中错过了一些可以提供优雅解决方案的东西吗?或者这是最不好的解决方案?

简单架构

信息(文件)

消息(文件) - > AggregatedMessage(directorySize) - >删除某些文件?

信息(文件)

1 个答案:

答案 0 :(得分:1)

Camel非常棒,但有时很难确切地看到使用哪种设计模式;)

首先,您需要保留文件对象的副本,因为在达到阈值之前您不知道是否删除它们 - 基本上(至少)有两种方法可以执行此操作。

备选方案1

第一种方法是在交换属性中使用List。无论您使用交换 body 做什么,此属性都会出现。如果你看一下GroupedExchangeAggregationStrategy的源代码,它就是这样做的:

        list = new ArrayList<Exchange>();
        answer.setProperty(Exchange.GROUPED_EXCHANGE, list);
        // ...
        list.add(newExchange);

或者您可以在自己的交易所属性上手动执行相同的操作。无论如何,像你一样使用Grouped聚合策略是完全没问题的。

备选方案2

“保留”旧邮件的第二种方法是将副本发送到已停止的SEDA队列。所以你会做to("seda:xyz")。您将此队列定义为.noAutoStartup()。然后你可以向它发送消息,他们将在由camel管理的内部队列中排队。当您想要处理消息时,只需通过controlbus启动它,然后再将其停止。

一般情况下,除非绝对必要,否则应该避免乱跑和停止队列,但这当然是另一种方法

建议的解决方案

我建议你照你所做的那样做(即替代方案1):

  • aggregate通过GroupedExchangeAggregationStrategy将各个文件保存在列表中
  • 计算总文件大小(使用处理器,或使用自定义聚合策略进行处理)
  • 使用filter(simple("${body} < 123"))
  • 通过splitter(simple("${property.CamelGroupedExchange}"))
  • “展开”您的汇总
  • 逐个删除文件

请告诉我这是否有意义,或者我是否以任何方式误解了您的问题。