Servlet缓冲响应尽管调用flush()

Kan*_*ane 9 java tomcat servlets

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

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

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

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

我该怎么做才能强制servlet发回真正小的初始数据?

Kan*_*ane 4

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