【发布时间】:2011-10-22 12:36:55
【问题描述】:
我们有一个系统,其中客户端发出 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();
}
}
我将浏览器超时设置为大约 20 秒,以便于复制。尽管多次写入 100 字节,但没有任何内容发送到浏览器并且浏览器超时。如果我扩大浏览器超时,则在写入 1000 个字节之前不会发送任何内容,然后浏览器会弹出“您要保存...”对话框。同样,在最初的 1000 字节之后,每增加 100 字节就可以正常发送,而不是缓冲到 1000 字节块。
如果我将 while 条件中的最大字节数设置为 200 左右,它工作正常,只发送 200 个字节。
我能做些什么来强制 servlet 发回非常少量的初始数据?
【问题讨论】:
-
您在什么操作系统下运行?我见过一个类似的问题,报告的 servlet 不会返回任何内容,除非输出的大小大于 1024 字节。通过查看 JavaDocs,它可能与操作系统如何处理其缓冲区有关。
-
Win7.我们最终决定它不在应用程序端,并强制应用程序只接受具有一定数据量的请求。
-
我相信这可能是一个应用服务器问题。请参阅my post。