Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在编写多个http响应时有任何限制吗?_Http_Proxy_Netty_Pipelining - Fatal编程技术网

在编写多个http响应时有任何限制吗?

在编写多个http响应时有任何限制吗?,http,proxy,netty,pipelining,Http,Proxy,Netty,Pipelining,我正在用netty构建一个支持HTTP管道的应用程序。因此,我在一个通道上接收多个HttpRequest对象,并获得匹配的HttpResponse对象。HttpResponse写入的顺序与我得到的HttpRequest的顺序相同。如果写入了HttpResponse,则当HttpProxyHandler接收到writeComplete事件时,将写入下一个响应 管道应方便: final ChannelPipeline pipeline = Channels.pipeline(); pipeline.

我正在用netty构建一个支持HTTP管道的应用程序。因此,我在一个通道上接收多个
HttpRequest
对象,并获得匹配的
HttpResponse
对象。
HttpResponse
写入的顺序与我得到的
HttpRequest
的顺序相同。如果写入了
HttpResponse
,则当
HttpProxyHandler
接收到
writeComplete
事件时,将写入下一个响应

管道应方便:

final ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("decoder", new HttpRequestDecoder());
pipeline.addLast("encoder", new HttpResponseEncoder());
pipeline.addLast("writer", new HttpResponseWriteDelayHandler());
pipeline.addLast("deflater", new HttpContentCompressor(9));
pipeline.addLast("handler", new HttpProxyHandler());
只考虑写入调用的顺序应该很重要,但为了确保我构建了另一个处理程序(
HttpResponseWriteDelayHandler
),它在写入整个响应之前抑制
writeComplete
事件

为了测试这一点,我在Firefox中启用了
network.http.proxy.pipeline
,并访问了一个包含许多图像和连接的页面()。问题是,尽管代理的日志认为它们是成功发送的,但浏览器没有收到某些响应。 我有一些发现:

  • 仅当从代理到服务器的连接速度快于从代理到浏览器的连接速度时,才会出现此问题
  • 在该连接上发送较大的图像(例如20kB)后,此问题更常发生
  • 如果仅发送了
    304-未修改
    响应(考虑浏览器缓存刷新页面),则不会出现问题
  • 设置
    bootstrap.setOption(“sendBufferSize”,1048576)或以上没有帮助
  • HttpResponseWriteDelayHandler
    中发送
    writeComplete
    事件之前,根据响应正文大小休眠一个时间段可以解决问题,但这是一个非常糟糕的解决方案

我找到了解决方案,如果其他人有类似问题,我想与大家分享:

HttpResponse
的内容太大。为了分析内容,整个HTML文档都在缓冲区中。必须再次将其拆分为多个块才能正确发送。如果
HttpResponse
没有分块,我就写了一个简单的解决方案。需要在逻辑处理程序旁边放置一个
ChunkedWriteHandler
,并编写此类而不是响应本身:

public class ChunkedHttpResponse implements ChunkedInput {

    private final static int       CHUNK_SIZE = 8196;
    private final HttpResponse     response;
    private final Queue<HttpChunk> chunks;
    private boolean                isResponseWritten;

    public ChunkedHttpResponse(final HttpResponse response) {
        if (response.isChunked())
            throw new IllegalArgumentException("response must not be chunked");

        this.chunks = new LinkedList<HttpChunk>();
        this.response = response;
        this.isResponseWritten = false;

        if (response.getContent().readableBytes() > CHUNK_SIZE) {
            while (CHUNK_SIZE < response.getContent().readableBytes()) {
                chunks.add(new DefaultHttpChunk(response.getContent().readSlice(CHUNK_SIZE)));
            }
            chunks.add(new DefaultHttpChunk(response.getContent().readSlice(response.getContent().readableBytes())));
            chunks.add(HttpChunk.LAST_CHUNK);

            response.setContent(ChannelBuffers.EMPTY_BUFFER);
            response.setChunked(true);
            response.setHeader(HttpHeaders.Names.TRANSFER_ENCODING, HttpHeaders.Values.CHUNKED);
        }
    }

    @Override
    public boolean hasNextChunk() throws Exception {
        return !isResponseWritten || !chunks.isEmpty();
    }

    @Override
    public Object nextChunk() throws Exception {
        if (!isResponseWritten) {
            isResponseWritten = true;
            return response;
        } else {
            HttpChunk chunk = chunks.poll();
            return chunk;
        }
    }

    @Override
    public boolean isEndOfInput() throws Exception {
        return isResponseWritten && chunks.isEmpty();
    }

    @Override
    public void close() {}
}
公共类ChunkedHttpResponse实现ChunkedInput{
私有最终静态整块大小=8196;
私人最终HttpResponse响应;
私有最终队列块;
私有布尔值被写入;
公共ChunkedHttpResponse(最终HttpResponse响应){
if(response.isChunked())
抛出新的IllegalArgumentException(“响应不能分块”);
this.chunks=新建LinkedList();
这个。反应=反应;
this.isresponsewrited=false;
if(response.getContent().readableBytes()>块大小){
while(CHUNK_SIZE
然后可以调用channel.write(new ChunkedHttpResponse(response),如果需要,就会自动完成分块