【问题标题】:how to stream a response over HTTP with netty如何使用 netty 通过 HTTP 流式传输响应
【发布时间】:2013-08-20 18:37:45
【问题描述】:

我使用的是 Netty 3.6.6,我想向调用者发送一个大响应。我无法将响应正文复制到 ChannelBuffer 中,因为在某些情况下它会非常大。

我正在将服务器从 CXF 迁移到 Netty,以前,我可以只使用 CXF 提供的 OutputStream 来写入数据。

我最初尝试只发送没有内容的响应,然后继续在一系列 8k 缓冲区中向 Channel 写入数据。这失败了,因为客户似乎得到了原始响应并且看不到任何数据并抱怨。我尝试将响应设置为分块,但这似乎没有什么区别,也没有设置分块标头,客户端总是看到一个空流。

我看到了 3.6.6 的文件服务器示例,这与我想做的类似,只是数据不会是文件。我看到了 ChunkedStream 和 NioStream,这似乎与我需要的很接近,除了它们采用 InputStream/ReadableByteChannel 而我有一个 OutputStream;我可以尝试使用 PipedInput 和 OutputStreams,但这似乎会引入一个不幸的瓶颈。

我确信有一种方法可以将大量数据流式传输回客户端以响应请求,但除非我有文件,否则我不知道该怎么做。

我也很好奇如果连接保持活动状态并且您正在流式传输内容但不知道内容长度,您如何让客户端知道响应已完成。在这些情况下,客户端似乎会永远等待连接关闭。

从 3.6.6 修改静态文件服务器示例以删除 content-length 标头(只需将其注释掉),指定其为分块响应

   response.setChunked(true);
   response.setHeader(Names.TRANSFER_ENCODING, Values.CHUNKED);

然后在写完响应后使用ChunkedNioStream发送文件:

    // Write the initial line and the header.
    ch.write(response);

    final ReadableByteChannel aIn = java.nio.channels.Channels.newChannel(new FileInputStream(file));
    ChannelFuture writeFuture = ch.write(new ChunkedNioStream(aIn));

产生不希望的行为,客户端获取几百个字节然后停止接收,基本上是我在应用程序中看到的。正确的事情似乎只发生在内容长度上,这在我的用例中是不可行的。

【问题讨论】:

    标签: netty


    【解决方案1】:

    当您尝试将ChunkedNioStream 写入ChunkedWriteHandler 时,它只会生成一个包含ChunkedNioStream 内容的流。也就是说,它产生ChannelBuffers 而不是HttpChunks。

    因为HttpMessageEncoder 只处理HttpMessageHttpChunk,所以ChunkedNioStream 产生的ChannelBuffer 被绕过到线路,没有附加HTTP 块头,导致浏览器混乱。

    要解决此问题,您必须实现自己的ChunkedInput,它会生成HttpChunks 而不是ChannelBuffers。但是,我必须同意这可能是一项具有挑战性的任务,因此您可能只想 fork HttpMessageEncoder 以便它也能理解 ChannelBuffer 并像对待 HttpChunk 一样对待它。请查看this partHttpMessageEncoder 了解更多信息。

    【讨论】:

    • 这似乎在 Netty 4.x 中用ChunkedInput 修复了,对吧?
    猜你喜欢
    • 2012-04-02
    • 1970-01-01
    • 2018-02-19
    • 2014-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-30
    相关资源
    最近更新 更多