我们正在使用camel 2.13.2 - 我有一个带有AggregationStrategy的组播路由 在每个多播分支中,我们有一个自定义的camel组件,它返回大量数据(大约4 MB)并写入Stream Cache(缓存输出流),我们需要聚合多播中的数据(聚合策略)。
在Aggregation策略中,我需要使用camel XPathBuilder进行XPath评估。 因此,我尝试读取正文并从StreamCache转换为byte []以避免在类型转换过程中出现错误:org.apache.camel.converter.stream.InputStreamCache。在XPathBuilder中。
当我尝试在聚合策略开始时读取正文时,我收到以下错误。
* / tmp / camel / camel-tmp-4e00bf8a-4a42-463a-b046-5ea2d7fc8161 / cos6047774870387520936.tmp(没有这样的文件或目录),原因:FileNotFoundException:/ tmp / camel / camel-tmp- 4e00bf8a-4a42-463a-b046-5ea2d7fc8161 / cos6047774870387520936.tmp(没有这样的文件或目录)。 at java.io.FileInputStream.open(Native Method) 在java.io.FileInputStream。(FileInputStream.java:138) at org.apache.camel.converter.stream.FileInputStreamCache.createInputStream(FileInputStreamCache.java:123)at org.apache.camel.converter.stream.FileInputStreamCache.getInputStream(FileInputStreamCache.java:117) at org.apache.camel.converter.stream.FileInputStreamCache.writeTo(FileInputStreamCache.java:93) 在org.apache.camel.converter.stream.StreamCacheConverter.convertToByteArray(StreamCacheConverter.java:102) at com.sap.it.rt.camel.aggregate.strategies.MergeAtXPathAggregationStrategy.convertToByteArray(MergeAtXPathAggregationStrategy.java:169) 在com.sap.it.rt.camel.aggregate.strategies.MergeAtXPathAggregationStrategy.convertToXpathCompatibleType(MergeAtXPathAggregationStrategy.java:161) *
以下是抛出错误的代码行:
Object body = exchange.getIn().getBody();
if( body instanceof StreamCache){
StreamCache cache = (StreamCache)body;
xml = new String(convertToByteArray(cache,exchange));
exchange.getIn().setBody(xml);
}
通过在多播相关路由中设置10MB的阈值来禁止流缓存写入文件,我们能够使用聚合策略。但我们不希望这样做,因为我们可能有更大的传入数据。
<camel:camelContext id="multicast_xml_1" streamCache="true">
<camel:properties>
<camel:property key="CamelCachedOutputStreamCipherTransformation" value="RC4"/>
<camel:property key="CamelCachedOutputStreamThreshold" value="100000000"/>
</camel:properties>
....
</camel:camelContext>
注意:如果我们在具有其他处理器的路由中使用基于StreamCache的camel组件但没有多播+聚合,则不会出现FileNotFound问题。
经过调试,我可以理解使用MulticastProcessor从StreamCache聚合大量数据的问题。
在MulticastProcessor.java中:调用doProcessParallel()并在完成多播的分支交换时,CachedOutputStream删除/清除临时文件。
甚至在多播分支交换到达聚合策略之前就会发生这种情况,聚合策略试图从分支交换机读取数据。如果StreamCache中存在大量数据,则临时文件已被删除,从而导致FileNotFound问题。
public CachedOutputStream(Exchange exchange, boolean closedOnCompletion) {
this.strategy = exchange.getContext().getStreamCachingStrategy();
currentStream = new CachedByteArrayOutputStream(strategy.getBufferSize());
if (closedOnCompletion) {
// add on completion so we can cleanup after the exchange is done such as deleting temporary files
exchange.addOnCompletion(new SynchronizationAdapter() {
@Override
public void onDone(Exchange exchange) {
try {
if (fileInputStreamCache != null) {
fileInputStreamCache.close();
}
close();
} catch (Exception e) {
LOG.warn("Error deleting temporary cache file: " + tempFile, e);
}
}
@Override
public String toString() {
return "OnCompletion[CachedOutputStream]";
}
});
}
}
public void close() throws IOException {
currentStream.close();
cleanUpTempFile();
}
如果我尝试设置closedOnCompletion = false,我可以绕过这个问题,同时在任何多播分支的任何组件中写入CachedOutputStream。
但这是一个漏洞的解决方案,因为streamcache临时文件可能永远不会被清除...因此我在读取AggregationStrategy中的数据后尝试关闭+清理缓存流。
是否可以调整MulticastProcessor以使多播分支交换仅在多播结束后聚合后达到“完成”状态?
请帮助/提供有关此问题的建议,因为我不熟悉使用camel Multicast。
谢谢, 拉克希米
答案 0 :(得分:1)
我尝试向Restlet请求发送大于1MB的JSON响应时抛出了类似的异常(是的,我知道1MB JSON太大了):
java.io.FileNotFoundException: C:\Users\me\AppData\Local\Temp\camel\camel-tmp-7ad6e098-538d-4d4c-9357-2b7addb1f19d\cos6725022584818060586.tmp (The system cannot find the file specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:146)
at org.apache.camel.converter.stream.FileInputStreamCache.createInputStream(FileInputStreamCache.java:123)
at org.apache.camel.converter.stream.FileInputStreamCache.getInputStream(FileInputStreamCache.java:117)
at org.apache.camel.converter.stream.FileInputStreamCache.read(FileInputStreamCache.java:112)
at java.io.InputStream.read(InputStream.java:170)
at java.io.InputStream.read(InputStream.java:101)
at org.restlet.engine.io.BioUtils.copy(BioUtils.java:81)
at org.restlet.representation.InputRepresentation.write(InputRepresentation.java:148)
at org.restlet.engine.adapter.ServerCall.writeResponseBody(ServerCall.java:510)
at org.restlet.engine.adapter.ServerCall.sendResponse(ServerCall.java:454)
at org.restlet.ext.servlet.internal.ServletCall.sendResponse(ServletCall.java:426)
at org.restlet.engine.adapter.ServerAdapter.commit(ServerAdapter.java:196)
at org.restlet.engine.adapter.HttpServerHelper.handle(HttpServerHelper.java:153)
at org.restlet.ext.servlet.ServerServlet.service(ServerServlet.java:1089)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:684)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1496)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:102)
相同的解决方法对我有用:
getContext().getProperties().put(CachedOutputStream.THRESHOLD, "" + THREE_MEGABYTE_TRESHOLD_BEFORE_FILE_CACHE);
我没有在这条路线中使用多播,只是简单的
重定时请求 - &gt;服务 - &gt;杰克逊马歇尔=&gt;错误
我使用Camel 2.14.0&amp; Restlet 2.2.2 with JDK 7 and Spring-boot 1.0.2 / Jetty