Tomcat не очищает буфер ответа - PullRequest
6 голосов
/ 29 марта 2012

Я протестировал HttpResponse#flushBuffer и PrintWriter#flush на Tomcat 7 ниже, но казалось, что ответ скорее проигнорировал их, чем спрятал содержимое поверх провода как можно скорее.

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");

    }

}

Браузер отображал«Привет» и «пока» вместе после задержки.Это неправильное поведение или намеренное?

@ EDIT

В соответствии с предложением @Tomasz Nurkiewicz, я снова протестировал с curl, после чего проблема исчезла.Кажется, что стандартные браузеры и tcp/ip monitor упаковывают small pieces of contents из одного и того же ответа HTTP, чтобы отобразить их вместе.

@ EDIT 2

Также замечено, что и HttpResponse#flushBuffer, и PrintWriter#flush приводят Tomcat 7 для отправки клиенту фрагментированных данных .

Ответы [ 4 ]

5 голосов
/ 06 декабря 2012

У меня была такая же проблема. Чтобы браузеры не дожидались загрузки страницы до того, как она выполнит рендеринг, вам нужно начать с:

response.setContentType("text/html;charset=UTF-8");
2 голосов
/ 23 марта 2016

У меня тоже была эта проблема. И я также обнаружил, что проблема исчезает с завитком. С некоторым фырканьем выяснилось, что виновником является gzip-кодирование. Чтобы сжать ответ, gzip ожидает, пока нижележащий PrintWriter не будет закрыт (то есть, пока не будет записан полный ответ), а затем выдает сжатый вывод. На стороне клиента это означает, что вы ничего не получите, пока не будет готов полный ответ. Curl, с другой стороны, не выдает на сервер gzip Accept-Encoding: gzip, и поэтому он работает, и вы можете получить чанкированный вывод как обычно.

2 голосов
/ 29 марта 2012

API для flushBuffer() очень точный:

Принудительно записывает любое содержимое в буфере для клиента . Вызов этого метода автоматически фиксирует ответ, то есть код состояния и заголовки будут записаны.

Таким образом, либо Tomcat не реализован в соответствии со спецификацией (буферизует более агрессивно и удерживает сбросы, если они слишком малы), либо клиент (браузер) ждет большего ввода, прежде чем фактически отобразить его.

Можете ли вы попробовать вместо этого или nc?

0 голосов
/ 20 января 2017

Еще не упомянутой возможной причиной этого явления является антивирусное программное обеспечение.Я наблюдал такое же поведение на моей машине: сервер отправлял фрагментированные данные, curl работал, обычные браузеры не работали, а также Fiddler подтвердил, что это был не тот сервер, который заблокировал.Поэтому через некоторое время я заподозрил, что веб-защита Sophos (антивирусное программное обеспечение, которое использует мой работодатель) вмешивается, и на самом деле они подтверждают на https://community.sophos.com/kb/en-us/115656, что они блокируют фрагментированные данные до тех пор, пока ответ не будет завершен, за исключением определенных случаев.mime-типы, которые часто используются для потоковой передачи мультимедийных данных.

В качестве быстрой проверки можно запустить демонстрацию HTTP-Push по адресу http://www.pushlets.com.. Если она не работает, вполне вероятно, что клиентимеет общую проблему с правильной обработкой фрагментированных данных типа text / html.

...