Apache camel 消息聚合的Camel条件

Apache camel 消息聚合的Camel条件,apache-camel,aggregation,Apache Camel,Aggregation,我正在寻找一种基于消息聚合有条件地处理消息的方法。我已经研究了很多方法来实现这一点,但Apache Camel似乎不支持它。我将解释这个场景,然后解释我尝试过的解决方案 情景: 我正在尝试有条件地清理目录。我每x天从目录中轮询一次,并获取所有文件(file://...). 我将其路由到一个聚合中,该聚合将文件聚合为单个大小(directorySize)。然后检查该大小是否超过某个阈值 这就是问题所在。如果此条件通过,我现在想删除某些文件,但我无法再访问原始消息,因为它们已聚合到新的exchang

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

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

这就是问题所在。如果此条件通过,我现在想删除某些文件,但我无法再访问原始消息,因为它们已聚合到新的exchange中

解决方案:

  • 我试图再次获取文件以处理它们。问题是,据我所知,你们不能让消费者按需取货。我尝试使用pollEnrich,但这将只获取一个文件,而不是目录中的所有文件
  • 我试图筛选/停止父路由。这里的问题是filter()/choice…stop()/end()只会停止具有目录大小的聚合路由,而不会停止具有文件消息的父路由。我不能有条件地处理这些
  • 我试图将聚合条件移动到我将调用的另一个路由,但这会导致与第一个解决方案相同的问题
我认为做的事情:

  • 重写聚合策略,不仅将大小聚合,还将文件本身聚合为groupedExchange。这样,我可以在检查后再次拆分聚合。我真的不喜欢这个解决方案,因为它会导致很多样板文件,无论是在代码中还是在运行时
  • 将文件大小计算器移动到处理器而不是聚合器。这首先会破坏使用骆驼的目的。。我将手动获取文件并添加大小。。而对于每一个文件
  • 使用ControlBus在该目录上动态启动删除路由。再一次,为了实现一些我认为应该能够用简单的方法来完成的事情,我做了大量的变通
  • 我想设置每个父消息的计算大小,但我不知道如何实现这一点
  • 另一种我没想到的阻止父路径的方法
我有点吃惊,你不能根据这些消息的聚合来优雅地过滤消息。我在《骆驼》中是否遗漏了一些可以提供优雅解决方案的东西?或者这是一个最不坏的解决方案

简单模式 消息(文件)

消息(文件)-->聚合消息(目录大小)-->是否删除某些文件


消息(文件)

骆驼真是太棒了,但有时确实很难确定要使用哪种设计模式;)

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

备选方案1

第一种方法是在exchange属性中使用
列表
。无论您如何处理exchange主体,此属性都将挂起。如果您查看一下
GroupedExchangeAgregationStrategy
的源代码,它正是这样做的:

        list = new ArrayList<Exchange>();
        answer.setProperty(Exchange.GROUPED_EXCHANGE, list);
        // ...
        list.add(newExchange);
list=newarraylist();
answer.setProperty(Exchange.group\u Exchange,list);
// ...
list.add(newExchange);
或者,您也可以在自己的exchange属性上手动执行相同的操作。在任何情况下,使用分组聚合策略完全可以

备选方案2

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

一般来说,除非绝对必要,否则应该避免在启动和停止队列时胡闹,但这肯定是另一种方式

建议的解决方案

我建议您按照您所做的做(即备选方案1):

  • aggregate
    通过GroupedExchangeAgregationStrategy将单个文件保存在列表中
  • 计算总文件大小(使用处理器,或者使用自定义聚合策略)
  • 使用
    过滤器(简单(“${body}<123”)
  • 通过
    拆分器(简单(“${property.CamelGroupedExchange}”)“展开”聚合
  • 逐个删除您的文件

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

您对此有何感受:来自(“file://location)至(“直接:测试”);from(“file//location?cron=…”).pollEnrich(“direct:test”).filter(…);这是别人向我建议的。我觉得这会导致更大的开销,但只要大小超过限制,就可以更灵活地删除eg-only文件,因为您每次都要进行计算。它还需要一些调整,例如删除读取锁,因为我同时从两个用户点读取目录。我不太熟悉在没有骆驼读锁的情况下删除文件的影响。我没有使用poll enricher-它看起来非常类似于polling consumer,它对您有用吗?文件锁-在删除文件之前,您需要找到一种方法来释放任何读锁,不幸的是,我在camel中没有这样做的经验。