isReady () возвращает true в закрытом состоянии - почему? - PullRequest
0 голосов
/ 29 июня 2018

ServletOutputStream.isReady() Javadoc говорит следующее :

Возвращает: истина, если запись в этот ServletOutputStream будет успешной, в противном случае возвращает ложь.

Несмотря на реализацию ServletOutputStream в Jetty, HttpOutput ведет себя довольно запутанно в случае, когда поток находится в состоянии CLOSED. Возвращает true:

case CLOSED:
    return true;

Источник: HttpOutput.java: 1011 .

Кроме того, все три write метода в HttpOutput выдают EofException, когда CLOSED:

case CLOSED:
    throw new EofException("Closed");

Так что кажется, что запись никогда не может быть успешной. В чем причина такого поведения?

1 Ответ

0 голосов
/ 29 июня 2018

Ключевой факт: Закрытый вызов подразумевает операцию записи.

Внутреннее состояние ЗАКРЫТО указывает, что использование потока / выхода ЗАКРЫТО для этой отправки (не то, что сам поток фактически закрыт).

Как мы попали в это состояние? Что-то вызвало ServletOutputStream.close() (и, в свою очередь, HttpOutput.close()), и теперь больше не разрешается запись в этот поток из текущей отправки.

В состоянии ЗАКРЫТО происходит сброс.

  • Флэш примет ответ
  • Сброс завершит запись различных буферов, присутствующих на различных слоях обмена / соединения / вывода.
  • Если имеется агрегатный буфер (для многих небольших записей), он записывает это.
  • Если есть слой сжатия (gzip), он также вызовет сброс.
  • Затем все эти буферы также проходят через слой Transfer-Encoding (например, chunked).
  • Затем происходит запись по сети.

HttpOutput также является единственной точкой вывода для всех вложенных запросов, например, с помощью include() из RequestDispatcher, которая снова откроет HttpOutput для использования во время include(), а затем закроет его снова.

Как только HttpOutput будет полностью и полностью очищен / завершен (больше не будет отправок, больше не будет записей и т. Д.), Тогда будет завершена окончательная очистка буфера, кодировки передачи завершены, HttpOutput сбрасывается, перерабатывается и возвращается к HttpConnection для использования со следующим обменом.

Мы могли бы лучше справиться с javadoc'ом в кодовой базе или, по крайней мере, использовать константы и имена переменных, которые имеют больше смысла.

Открыт https://github.com/eclipse/jetty.project/issues/2687

Относительно причала EofException (не JVM EOFException) при записи.

Как только ServletOutputStream ЗАКРЫТ для использования в конкретной диспетчеризации, дальнейшие вызовы на write() приведут к Jetty EofException.

Существует также разновидность EofException, в которой данные о ваших подтвержденных ответах были нарушены.

Например: вы объявили ответ Content-Length, скажем, 40 МБ, но написали 41 МБ, вы превысили возможности этого подтвержденного ответа, это исключение IOException. И спецификация Servlet говорит нам, чтобы мы бросили IOException в этом случае.

Jetty выбросит внутренний Jetty EofException (что расширяет IOException), чтобы указать этот конкретный сценарий и прервать соединение, нарушив любую устойчивость соединения, которую вы, возможно, хотели.

...