使用分块编码时CXF缓冲数据

时间:2013-12-18 20:15:57

标签: java cxf chunked-encoding

我使用Apache CXF 2.5.1编写了一个java REST(流)servlet,并将其部署到Tomcat 7.0.42容器中。 REST端点本质上是 StreamingOutput 的实现,它包含一个 Response 对象,当客户端请求时,该对象将被传递给容器。 / p>

服务的本质是将传感器数据流返回给客户端。理论上,这个流可以无限长,因为它只在客户端断开连接时终止。当传感器产生的数据量很小时,就会出现问题。

服务“有效”,但是当涉及到客户端收到的数据响应的大小时,我遇到了一个问题。客户端仅在服务中断8192字节阈值后才接收数据。然后客户端接收800字节,然后是8192字节,然后是800字节......

我希望一旦我在OutputStream上调用flush就将数据发送到客户端,容器将其移交给我的StreamingOutput实现。但是,我给出的OutputStream的实现(org.apache.cxf.transport.http.AbstractHTTPDestination中定义的WrappedOutputStream)有一个flush方法,它什么都不做。

有没有办法对CXF使用的OutputStream进行更多控制,以便我可以根据需要“刷新”到客户端?

3 个答案:

答案 0 :(得分:2)

最终,我能够按需刷新缓冲区的方法是创建一个CXF过滤器,特别是ResponseHandler的实现。

在过滤器中,我从Message实现中抓取了HttpServletResponse和CXF使用的OutputStream实现(不允许我刷新的实现),将它们包装在FilteredOutputStream中。每当调用flush时,我都会在HttpServletResponse上显式调用flush。

这是特定于CXF的,这样做会产生更多的开销,具体取决于调用flush的频率,但它确实允许“慢”流更快地到达客户端。

请评论我可能需要关注的任何问题或事情。

答案 1 :(得分:1)

您需要检查两件事。首先,您可能需要设置Content-Length头(response.setHeader()),其次,您可能需要设置缓冲区大小(response.setBufferSize())。这里似乎有一个讨论:

How do disable Transfer-Encoding in Tomcat 6

答案 2 :(得分:1)

一旦执行flush(),Tomcat本身就应该提交响应。这可能是CXF的一个问题。

如果你想要一个建议,我可能会建议你切换到使用这种应用程序:它更适合从服务器到客户端的长期数据流(或者反之亦然)。如果你不喜欢WebSocket,你至少应该看看Servlet 3.0规范的异步I / O甚至是Comet(尽管3.0-async是支持IMO的更好选择)。