【问题标题】:CXF buffering data when using chunked encoding使用分块编码时的 CXF 缓冲数据
【发布时间】:2014-01-07 04:27:32
【问题描述】:

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

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

该服务“有效”,但在客户端收到的数据响应的大小方面遇到了问题。客户端仅在服务突破 8192 字节阈值后接收数据。然后客户端收到 800 字节,然后是 8192 字节,然后是 800 字节……

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

有什么方法可以更好地控制 CXF 使用的 OutputStream,以便我可以按需“刷新”到客户端?

【问题讨论】:

    标签: java cxf chunked-encoding


    【解决方案1】:

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

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

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

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

    【讨论】:

    【解决方案2】:

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

    How do disable Transfer-Encoding in Tomcat 6

    【讨论】:

    • setHeader 和 setBufferSize 都不在 Response 的合约中。我也没有尝试禁用分块。禁用它对我有什么帮助?我很确定我想要分块,我只是想让 CXF 使用一个尊重我调用 flush() 的 OutputStream。
    • 嗯..我不确定您是否可以进行分块并始终强制刷新。
    【解决方案3】:

    Tomcat 本身应该在您执行flush() 后立即提交响应。这可能是 CXF 的问题。

    如果您愿意接受建议,我可能会建议您将 用于此类应用程序:它更适合从服务器到客户端的长期数据流(甚至反之亦然) -反之亦然)。如果你不喜欢 WebSocket,你至少应该看看 Servlet 3.0-spec 异步 I/O 甚至 Comet(尽管 3.0-async 是 IMO 支持的更好选择等等)。

    【讨论】:

      猜你喜欢
      • 2010-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多