1

我有一条需要通过 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。

“流”和onCompletion不兼容还是我做错了什么?

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

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

1 回答 1

4

组件 将为文件的每一行创建一个新的交换。

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

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

此选项用于创建 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 文档):

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

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

显然,实际上没有办法知道文件的结尾何时发生在流组件中。

一个不错的方法可能是在splitter中拥有一个 CamelSplitComplete 属性。我们可以这样使用(参见onCompletion 和 onWhen 谓词章节):

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

编辑:我只是在寻找流消费者,但因为你也在使用生产者。查看 closeOnDone 属性,这可能会奏效。

关闭完成 | 假 | Camel 2.11.0:此选项与 Splitter 结合使用并流式传输到同一文件。这个想法是保持流打开并且仅在拆分器完成时关闭,以提高性能。请注意,这要求您只流式传输到同一个文件,而不是 2 个或更多文件。

于 2013-10-22T08:16:14.620 回答