【问题标题】:Tomcat does not flush the response bufferTomcat 不刷新响应缓冲区
【发布时间】:2012-04-12 20:32:22
【问题描述】:

我在下面的Tomcat 7 上测试了HttpResponse#flushBufferPrintWriter#flush,但似乎响应宁愿忽略它们,而不是像预期的那样尽快通过网络刷新内容。

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {

        PrintWriter pw = response.getWriter();
        pw.println("say hi now");
        pw.flush();
        response.flushBuffer();
        try {
            Thread.sleep(5000);
        } catch (Exception e) {
        }
        pw.println("say bye in 5 seconds");

    }

}

延迟后浏览器同时显示“hi”和“bye”。这是不当行为还是故意的?

@EDIT

根据@Tomasz Nurkiewicz 的建议,我再次使用curl 进行了测试,然后问题就消失了。似乎标准浏览器和 tcp/ip monitor 从同一个 http 响应中打包 small pieces of contents 以将它们一起呈现。

@EDIT 2

还观察到HttpResponse#flushBufferPrintWriter#flush 都驱动Tomcat 7 发送客户端chunked data

【问题讨论】:

  • 我相信这是一个应用服务器配置。请参阅my post

标签: java tomcat servlets tomcat7


【解决方案1】:

我也遇到了同样的问题。要停止浏览器等到页面完成加载后再进行任何渲染,您需要开始:

response.setContentType("text/html;charset=UTF-8");

【讨论】:

    【解决方案2】:

    flushBuffer() 的 API 非常精确:

    强制将缓冲区中的任何内容写入客户端。调用此方法会自动提交响应,这意味着将写入状态代码和标头。

    因此,要么 Tomcat 没有按照规范实现(缓冲区更积极,如果它们太小则保持刷新),或者客户端(浏览器)在实际渲染之前等待更多输入。

    您可以尝试改用nc 吗?

    【讨论】:

    • 我通过网络窥探,这是 tomcat 上的一个实现问题。
    • 如果尝试使用curl,问题就消失了。 tomcat 应该是unrelated
    【解决方案3】:

    我也有这个问题。我也发现这个问题随着 curl 消失了。 经过一番嗅探,原来罪魁祸首是 gzip 编码。为了压缩响应,gzip 一直等到底层的 PrintWriter 关闭(即,直到写入完整的响应),然后生成压缩输出。在客户端,这意味着在完整响应准备好之前您不会得到任何回报。另一方面,Curl 不会向服务器发出 Accept-Encoding: gzip,这就是它起作用的原因,您可以按预期正常获得分块输出。

    【讨论】:

      【解决方案4】:

      导致这种现象的一个尚未提及的可能原因是防病毒软件。我确实在我的机器上观察到了相同的行为:服务器发送分块数据,curl 工作,普通浏览器没有,而且 Fiddler 确认不是服务器阻止了。所以过了一会儿,我怀疑 Sophos(我的雇主使用的防病毒软件)的网络保护会干扰,事实上他们在https://community.sophos.com/kb/en-us/115656 确认他们会阻止分块数据,直到响应完成,除了某些 mime 类型通常用于流媒体数据。

      作为一项快速检查,您可以在http://www.pushlets.com 运行 HTTP-Push 演示。如果它不起作用,则客户端很可能在正确处理 text/html 类型的分块数据方面存在一般问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-07-11
        • 1970-01-01
        • 2011-07-11
        • 2015-08-10
        • 1970-01-01
        • 2011-11-28
        相关资源
        最近更新 更多