Servlet缓冲响应尽管调用flush() [英] Servlet buffering response despite calls to flush()

查看:200
本文介绍了Servlet缓冲响应尽管调用flush()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个系统,客户端发出HTTP GET请求,系统对后端进行一些处理,压缩结果,然后将其发送给客户端。由于处理可能需要一些时间,我们将此作为 ZipOutputStream 包装 response.getOutputStream()

We have a system where a client makes an HTTP GET request, the system does some processing on the backend, zips the results, and sends it to the client. Since the processing can take some time, we send this as a ZipOutputStream wrapping the response.getOutputStream().

然而,当我们在第一个 ZipEntry 中有非常少量的数据时,第二个条目需要一个很长一段时间,客户端使用的浏览器超时。我们已经尝试刷新流缓冲区,但是在向流写入至少1000个字节之前,似乎没有响应发送到浏览器。奇怪的是,一旦发送了前1000个字节,后续的刷新似乎工作正常。

However, when we have an exceptionally small amount of data in the first ZipEntry, and the second entry takes a long time, the browser the client is using times out. We've tried flushing the stream buffer, but no response seems to be sent to the browser until at least 1000 bytes have been written to the stream. Oddly, once the first 1000 bytes have been sent, subsequent flushes seem to work fine.

我尝试将代码拆解为裸露的例子:

I tried stripping down the code to bare-bones to give an example:

protected void doGet(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException {
    try {
        ZipOutputStream _zos = new ZipOutputStream( response.getOutputStream());
        ZipEntry _ze = null;
        long startTime = System.currentTimeMillis();
        long _lByteCount = 0;

        response.setContentType("application/zip");

        while (_lByteCount < 2000) {
            _ze = new ZipEntry("foo");
            _zos.putNextEntry( _ze );

            //writes 100 bytes and then waits 10 seconds
            _lByteCount += StreamWriter.write( 
                    new ByteArrayInputStream(DataGenerator.getOutput().toByteArray()),
                    _zos );
            System.out.println("Zip: " + _lByteCount + " Time: " + ((System.currentTimeMillis() - startTime) / 1000));

            //trying to flush
            _zos.finish();
            _zos.flush();
            response.flushBuffer();
            response.getOutputStream().flush();
        }
    } catch (Throwable e) {
        e.printStackTrace();
    }
}

我将浏览器超时设置为大约20秒容易再现。尽管多次写入100个字节,但没有任何内容发送到浏览器并且浏览器超时。如果我扩展浏览器超时,则在写入1000个字节之前不会发送任何内容,然后浏览器会弹出是否要保存...对话框。再次,在最初的1000个字节之后,每个加法100个字节发送正常,而不是缓冲到1000个字节的块。

I set my browser timeout to be about 20 seconds for easy reproduction. Despite writing the 100 bytes a couple of times, nothing is sent to the browser and the browser times out. If I expand the browser timeout, nothing gets sent until 1000 bytes have been written and then the browser pops up the "Would you like to save..." dialog. Again, after the initial 1000 bytes, each addition 100 bytes sends fine, rather than buffering to 1000 byte chunks.

如果我将while条件中的最大字节数设置为200左右,它工作正常,只发送200个字节。

If I set the max byte count in the while condition to 200 or so, it works fine, sending only 200 bytes.

我可以做些什么来强制servlet发回真正小的初始数据?

What can I do to force the servlet to send back really small initial amounts of data?

推荐答案

事实证明,底层的Apache / Windows IP堆栈有一个限制,它可以缓冲流中的数据,以提高效率。由于大多数人都存在太多数据的问题,而不是太少数据的问题,这在大多数时候都是正确的。我们最终做的是要求用户请求足够的数据,以便在超时之前达到1000字节限制。很抱歉花了这么长时间来回答这个问题。

It turns out there is a limit on the underlying Apache/Windows IP stack that buffers data from a stream in an attempt to be efficient. Since most people have the problem of too much data, not the problem of too little data, this is right most of the time. What we ended up doing was requiring the user to request enough data that we'd hit the 1000 byte limit before timing out. Sorry for taking so long to answer the question.

这篇关于Servlet缓冲响应尽管调用flush()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆