【发布时间】:2016-08-01 06:21:54
【问题描述】:
我正在研究“在 Apache Camel 中使用缓存以及如何处理大文件”的主题。
目的是用骆驼处理大文件而不将文件加载到内存中,因为它是一个超过 5 GO 的大文件。
我们找到了几个轨道,第一个轨道是使用拆分器组件,让我们可以逐行或逐块读取文件,但是如果我们使用拆分器,我们将无法再次读取文件从一开始,功能需求就是即使在拆分完成时也能够读取文件的某些部分。
所以我们必须使用缓存系统,将块放入缓存中以重复使用它们。
所以我们认为必须使用 CachedOutputStream 类将分割器后的部分文件写入磁盘,该类还提供了对磁盘上的数据进行加密的能力。
下面的例子:
<camelContext xmlns="http://camel.apache.org/schema/spring" trace="false" streamCache="true">
<streamCaching id="myCacheConfig" spoolDirectory="target/cachedir" spoolThreshold="16"/>
<route id="SPLIT-FLOW" streamCache="true">
<from uri="file:src/data/forSplitCaching\SimpleRecord?noop=true"/>
<split streaming="true">
<tokenize token="\n"/>
<to uri="direct:PROCESS-BUSINESS"/>
</split>
</route>
<route id="PROCESS-BUSINESS" streamCache="true">
<from uri="direct:PROCESS-BUSINESS"/>
<bean ref="ProcessBusiness" method="dealRecord"/>
<choice>
<when>
<simple>${in.header.CamelSplitComplete} == "true"</simple>
<to uri="direct:STREAM-CACHING"/>
</when>
</choice>
</route>
<route id="STREAM-CACHING">
<from uri="direct:STREAM-CACHING"/>
<bean ref="ProcessStreamCaching" method="usingStream"/>
<setHeader headerName="CamelFileName">
<simple>${header.CamelFileName}.${header.CamelSplitIndex}</simple>
</setHeader>
<to uri="file:src/out"/>
</route>
</camelContext>
dealRecord 方法将分割后的每一行放入一个缓存中:
public void dealRecord(Exchange exchange) throws Exception {
String body;
File file;
String[] files;
boolean isSplitComplete;
body = (String) exchange.getIn().getBody();
isSplitComplete = (boolean) exchange.getProperties().get("CamelSplitComplete");
CachedOutputStream cos = new CachedOutputStream(exchange, false);
cos.write(body.getBytes("UTF-8"));
file = new File("target/cachedir");
files = file.list();
for (String nameTmpfile : files) {
LOG.info("Genered File [" + nameTmpfile + "]");
}
lstCache.add(cos);
if(isSplitComplete){
exchange.getIn().setHeader("Cached",lstCache);
}
}
使用Stream的方法,可以使用header中存在的每一个缓存
public byte[] usingStream(Exchange exchange) throws InputStreamException {
final ArrayList<CachedOutputStream> lstcache;
byte[] bytesMessage;
StringBuilder messageCompleteOut = new StringBuilder();
InputStream is = null;
lstcache = (ArrayList<CachedOutputStream>) exchange.getIn().getHeader("Cached");
for (CachedOutputStream oneCache : lstcache) {
try {
is = oneCache.getWrappedInputStream();
String messageInputstream = toString(is);
LOG.info("Message of Cache ["+ messageInputstream +"]");
messageCompleteOut.append(messageInputstream);
messageCompleteOut.append(System.lineSeparator());
} catch (IOException e) {
LOG.error(InputStreamException.ERROR_MANIPULATING_INPUT_STREAM_CHANNEL);
throw new InputStreamException(InputStreamException.ERROR_MANIPULATING_INPUT_STREAM_CHANNEL,e);
}
// On ferme le flux
IOHelper.close(is);
}
bytesMessage = messageCompleteOut.toString().getBytes(Charset.forName("UTF-8"));
return bytesMessage;
}
这个解决方案看起来不错吗?或者也许有更好的方法?
谢谢
【问题讨论】:
标签: java xml caching apache-camel