0

我正在使用 camel-cxfrs 组件来映射一个简单的 REST GET 操作,该操作返回从外部资源中提取的数据。一切正常,直到我决定启用“streamCache”,因为要返回的数据有时可能非常大(高达 50MB),我们不想将它加载到内存中,否则当执行多个请求时我们会耗尽内存同时!所以我配置了一个 DefaultStreamCachingStrategy 来定义何时将数据流式传输到 tmp 文件(例如大于 1MB 的数据)。

这工作正常,一旦从外部资源(DB 中的 blob !!)获取我的数据,它就会流回调用者,并且由于数据大于阈值,Camel 正在将我的输入流转换为 FileInputStreamCache,这很好......直到响应准备好通过 CXF 组件返回给调用者!因为消息传递给CXF组件,不再需要Camel交换(输出消息离开Camel上下文),所以创建的tmp文件在内容完全返回给REST之前被Camel删除(由它的TempFileManager实现)客户!!
这会导致 IOException,因为 CXF 组件试图从输入流(刚刚被 Camel 关闭)读取数据到 http 客户端。

知道如何解决这个问题吗?我需要保持 tmp 文件处于打开状态,直到所有响应数据都可以发送回 REST 客户端。但是一旦发送响应,就必须关闭并删除它。

这里我的骆驼上下文和一些豆子是如何定义的(没有显示一切):

<!-- ... -->
<cxf:rsServer address="/path" id="rsServer">
    <cxf:providers>
        <!-- ... -->
    </cxf:providers>
    <cxf:serviceBeans>
        <ref bean="resourcesEndpoint"/>
    </cxf:serviceBeans>
    <!-- ... -->
</cxf:rsServer>
<!-- ... -->

<bean class="org.apache.camel.impl.DefaultStreamCachingStrategy" id="streamStrategy">
    <property name="enabled" value="true"/>
    <property name="bufferSize" value="512000"/>
    <property name="spoolThreshold" value="512000"/>
    <property name="spoolUsedHeapMemoryThreshold" value="8}"/>
    <property name="spoolUsedHeapMemoryLimit" value="Max"/>
    <property name="removeSpoolDirectoryWhenStopping" value="true"/>
    <property name="anySpoolRules" value="true"/>
</bean>
<!-- ... -->

<camelContext id="context" streamCache="true" trace="false" useBreadcrumb="true" useMDCLogging="true" xmlns="http://camel.apache.org/schema/spring">
    <!-- ... -->
    <route id="mainRoute" >
        <from id="fromCXFEndpoint" uri="cxfrs:bean:rsServer?bindingStyle=SimpleConsumer"/>
        <recipientList id="_recipientList1">
            <simple>direct:${header.operationName}</simple>
        </recipientList>
    </route>
    <route id="downloadDataRoute" >
        <from id="fromDownloadDataCXF" uri="direct:downloadData"/>
        <!-- ... -->
        <!-- Performing data fetching... not showing everything here! -->
        <!-- ... -->
    </route>
</camelContext>

接下来,用于映射 REST 请求的端点类:

@Path("/resources")
@Component
@Service
public class ResourcesEndpoint {

    @GET
    @Path("/data/{guid}")
    @Produces({MediaType.TEXT_PLAIN, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_OCTET_STREAM})
    public StreamingOutput downloadData(@PathParam("guid") String guid) {
        return null;
    }
}
4

0 回答 0