我们有一个系统,客户端发出 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 发回非常少量的初始数据?
事实证明,为了提高效率而缓冲流中的数据的底层 Apache/Windows IP 堆栈存在限制。因为大多数人都会遇到这样的问题too much数据,而不是问题太少了数据,大多数时候这是正确的。我们最终要做的是要求用户请求足够的数据,以便在超时之前达到 1000 字节的限制。抱歉花了这么长时间才回答这个问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)