Apache Camel:使用stream和onCompletion

时间:2013-10-21 12:40:06

标签: java stream apache-camel

我有一条路线需要通过HTTP下载一个文件。

当收到包含命令(包含HTTP资源的URL,以及保存它的本地文件的URI)的消息时,动态添加此路由,然后在文件传输完成时我想删除路由,因此只使用Camel作为协议转换器。

我正在使用Camel,因为这条路线属于基于EIP的项目,其中Camel随处可用于消息传递和集成。

我用过:

onCompletion().setBody(simple("")).bean(new Stop(getContext(), transferID));

from("stream:url?url="+from).to("stream:file?fileName="+to).routeId(this.transferID);

(文件大,10-100 Gb)

我看到onCompletion在整个文件传输之前触发,实际上它只传输不可预测的字节数,例如100-300 kB。

“stream”和onCompletion不兼容,还是我做错了?

编辑:在我正在做的Bean中:

c.stopRoute(transferID);
c.removeRoute(transferID);

1 个答案:

答案 0 :(得分:2)

stream component 会为文件的每一行创建一个新的交换。

流组件提供了在XX行上拆分的选项(默认为0):

  

groupLines 0 Camel 2.5:将消费者中的X行分组。   例如,对10行进行分组,因此只吐出一个Exchange   10行,而不是每行1个。

此选项用于创建XX行的新交换。以下是StreamConsumer的相关代码:

 if (lines.size() >= endpoint.getGroupLines()) {
      // spit out lines
      Exchange exchange = endpoint.createExchange();

      // create message with the lines
      Message msg = new DefaultMessage();
      List<String> copy = new ArrayList<String>(lines);
      msg.setBody(endpoint.getGroupStrategy().groupLines(copy));
      exchange.setIn(msg);

      // clear lines
      lines.clear();

      getProcessor().process(exchange);
 }

每次交换完成后 onCompletion都会执行

来自骆驼文档(onCompletion documentation):

  

始终触发,仅在成功完成时触发,或仅触发   失败

因此,您的代码会在读取第一行后停止路径

显然,实际上无法知道文件末尾何时与流组件一起发生。

一个很好的方法可能是拥有像splitter中的CamelSplitComplete属性。 我们可以这样使用(参见onCompletion with onWhen predicate章节):

onCompletion()
  .onWhen(property("CamelSplitComplete").isEqualTo("true"))
  .setBody(simple("")).bean(new Stop(getContext(), transferID));

编辑:我只是在寻找流消费者,但是因为你也在使用制作人。查看closeOnDone属性,这可能会起到作用。

  

closeOnDone |假| Camel 2.11.0:此选项组合使用   使用Splitter并流式传输到同一个文件。我的想法是保持   当Splitter完成时,流开放并且只关闭,以改善   性能。请注意,这需要您只流式传输到同一个文件,   而不是2个或更多文件。