У соединителя Tomcat 9 HTTP2 возникли проблемы с отправкой байтового массива с помощью ResponseEntity - PullRequest
0 голосов
/ 22 октября 2018

Я провел день, борясь с этой очень странной проблемой.Вот мой очень простой метод контроллера:

    @GetMapping("/bigfile") 
public ResponseEntity<byte[]> big() {
    final byte[] someBytes = new byte[10 * 1000 * 1000];
    LOG.info("I want to write: " + someBytes.length + " bytes");
    final HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.setContentLength(someBytes.length);
    httpHeaders.setContentType(IMAGE_PNG);
    return new ResponseEntity<>(someBytes, httpHeaders, OK);
}

Очень простой материал.Он отправляет 10 Мбайт нулевых байтов как PNG.Это должно "просто работать" легко.(Очевидно, что это недопустимые изображения PNG. Моя цель - отправить в качестве примера длинный байтовый массив.) И это так.Он отлично работает.

Пока я не переключу Tomcat на использование HTTP / 2, добавив:

<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol"                                              
                   keepAliveTimeout="20000"/> 

в конфигурацию хоста.Затем он начинает разрывать соединение после примерно 1 Мб до 3 Мб передачи, и я вижу такие ошибки, как:

org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipe
    at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:333) ~[catalina.jar:9.0.12]
    at org.apache.catalina.connector.OutputBuffer.appendByteArray(OutputBuffer.java:728) ~[catalina.jar:9.0.12]
    at org.apache.catalina.connector.OutputBuffer.append(OutputBuffer.java:657) ~[catalina.jar:9.0.12]
    at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:368) ~[catalina.jar:9.0.12]
    at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:346) ~[catalina.jar:9.0.12]
    at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:96) ~[catalina.jar:9.0.12]
    at     org.springframework.security.web.util.OnCommittedResponseWrapper$SaveContextServletOutputStream.write(OnCommittedResponseWrapper.java:639) ~[spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at     org.springframework.security.web.util.OnCommittedResponseWrapper$SaveContextServletOutputStream.write(OnCommittedResponseWrapper.java:639) ~[spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at java.base/java.io.InputStream.transferTo(InputStream.java:522) ~[na:na]

Это сводит меня с ума.Простое решение состоит в том, чтобы просто не использовать HTTP / 2, что, вероятно, является решением, которое мне нужно использовать.Есть объяснения?Я что-то упустил, или это ошибка в Tomcat HTTP / 2?Для реального производственного использования это подтверждает мне, что я не должен использовать Tomcat в качестве фактического внешнего интерфейса, а скорее я должен использовать Nginx и прокси для Tomcat.Но я надеялся отложить это на потом.

1 Ответ

0 голосов
/ 22 октября 2018

Думаю, я понял это.Я не знаю, что там делал keepAliveTimeout, но я вынул его, а затем снова протестировал, и это сработало.Затем я увеличил размер байтового массива до 100 Мб, и это сработало.Я оставлю этот ответ здесь для всех, кто сталкивается с этой ситуацией.Я все еще считаю, что лучше использовать Nginx в качестве внешнего интерфейса для реальных развертываний.

...