如何使用netty通过HTTP流式传输响应 [英] how to stream a response over HTTP with netty
问题描述
我正在使用Netty 3.6.6,我想将较大的响应发送回给呼叫者.我无法将响应主体复制到ChannelBuffer中,因为在某些情况下,响应主体会很大.
I'm using Netty 3.6.6 and I'd like to send a large response back to the caller. I can't copy the response body into a ChannelBuffer as in some cases it will be very large.
我要将服务器从CXF迁移到Netty,以前,我只能使用CXF提供的OutputStream写入数据.
I'm migrating a server from CXF to Netty, previously, I could just use the OutputStream provided by CXF to write the data.
我最初试图只发送不带内容的响应,然后继续在一系列8k缓冲区中将数据写入Channel.这失败了,因为客户似乎得到了原始答复,没有看到任何数据并且抱怨.我尝试将响应设置为分块,但这似乎没有什么区别,也没有设置分块标头,客户端始终看到一个空流.
I originally tried to just send the response without content, and then continued to write data to the Channel in a series of 8k buffers. This failed as the client seemed to get the original response and see no data and complain. I tried setting the response as chunked, but this didnt seem to make a difference, nor did setting the chunked header, the client always saw an empty stream.
我看到了3.6.6的文件服务器示例,该示例与我要执行的操作类似,只是数据不会是文件.我看到了ChunkedStream& NioStream,看起来很接近我的需要,除了它们使用InputStream/ReadableByteChannel,而我拥有一个OutputStream之外;我可以尝试使用PipedInput& OutputStreams,但这似乎会带来不幸的瓶颈.
I saw the file server example for 3.6.6, and that's similar to what I want to do, except the data will not be a file. I saw the ChunkedStream & NioStream, which seemed close to what I need, except they take InputStream/ReadableByteChannel whereas I have an OutputStream; I could try using the PipedInput & OutputStreams, but that seems like it would introduce an unfortunate bottleneck.
我确定有一种方法可以将大量数据流回客户端以响应请求,但是除非有文件,否则我只是不知道如何做.
I'm sure there's a way to stream a lot of data back to the client in response to a request, but I'm just not seeing how to do it unless I have a file.
我也很好奇,如果连接保持活动状态,并且您正在流式传输内容,但您不知道内容的长度,您如何让客户端知道响应已完成.在这种情况下,客户端似乎会永远等待连接关闭.
I am also curious how you let the client know the response is complete if the connection is keep-alive, and you're streaming content, but don't know the content length. Seems like the client would wait forever for the connection to close in those cases.
从3.6.6修改静态文件服务器示例以删除content-length标头(只需将其注释掉),指定其为分块响应
Modifying the static file server example from 3.6.6 to remove the content-length header (just comment it out), specify that its a chunked response
response.setChunked(true);
response.setHeader(Names.TRANSFER_ENCODING, Values.CHUNKED);
,然后在写入响应后使用ChunkedNioStream
发送文件:
and then using ChunkedNioStream
to send the file after writing the response:
// 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));
产生了不希望的行为,客户端获得了数百个字节,然后停止接收,基本上就是我在应用程序中看到的内容.正确的事情似乎只发生在content-length上,这在我的用例中是不可行的.
Yields the undesired behavior, the client gets a couple hundred bytes and then stop receiving, basically what I'm seeing in my application. The correct thing only seems to happen with a content-length, which is not feasible in my use case.
推荐答案
当您尝试将ChunkedNioStream
写入ChunkedWriteHandler
时,它只会生成一个流,其中包含ChunkedNioStream
only .也就是说,它生成的是ChannelBuffer
而不是HttpChunk
.
When you attempt to write a ChunkedNioStream
to ChunkedWriteHandler
, it merely produces a stream which contains the content of the ChunkedNioStream
only. That is, it produces ChannelBuffer
s rather than HttpChunk
s.
因为HttpMessageEncoder
仅处理HttpMessage
和HttpChunk
,所以ChunkedNioStream
生成的ChannelBuffer
被绕过了线路,没有前置HTTP块头,从而导致浏览器混乱.
Because HttpMessageEncoder
handles only HttpMessage
and HttpChunk
, ChannelBuffer
produced by ChunkedNioStream
is bypassed to the wire, without HTTP chunk header prepended, causing your browser confused.
要解决此问题,您必须实现自己的ChunkedInput
,该ChunkedInput
生成HttpChunk
而不是ChannelBuffer
.但是,我必须同意这可能是一项艰巨的任务,因此您可能只想分叉HttpMessageEncoder
,以便它也理解ChannelBuffer
并将其像HttpChunk
一样对待.请查看
To fix this problem, you have to implement your own ChunkedInput
which produces HttpChunk
s instead of ChannelBuffer
s. However, I must agree that this might be a challenging task, so you might just want to fork HttpMessageEncoder
so that it also understands ChannelBuffer
and treats it just like HttpChunk
. Please take a look at this part of HttpMessageEncoder
for more information.
这篇关于如何使用netty通过HTTP流式传输响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!