Tomcat 9 HTTP2连接器在使用ResponseEntity发送字节数组时遇到问题

时间:2018-10-22 05:34:47

标签: tomcat http2

我整天都在与这个非常奇怪的问题作斗争。这是我非常简单的控制器方法:

    @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);
}

非常基本的东西。它正在发送10mb的零字节作为PNG。这应该很容易“工作”。 (显然,这不是有效的PNG图像。我的目的是发送一个长字节数组作为示例。)效果很好。

在输入以下内容之前,我将Tomcat切换为使用HTTP / 2:

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

在我的主机配置中。然后,它通常在大约1mb到3mb的传输后开始断开连接,我看到如下错误:

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。但是我希望把它推迟到以后。

2 个答案:

答案 0 :(得分:1)

我目前对 Http2Protocol 有类似的错误。向servlet上传数据时,连接中途关闭。当我返回一个字节数组时,Chrome 有时会返回消息 ERR_HTTP2_PROTOCOL_ERROR,并且大部分时间它都可以工作。这只是偶尔发生,但在生产使用中非常烦人。

它还只是帮助我从配置中删除了 HTTP/2,默认情况下未设置 keepAliveTimeout

  • 我使用 Tomcat 9.0.40 版
  • 我也很想知道这是 Tomcat 中的错误还是我的配置错误。

答案 1 :(得分:0)

我想我明白了。我不知道keepAliveTimeout在里面做什么,但是我把它拿出来,然后再次测试就可以了。然后,我将字节数组的大小增加到100mb,并且可以正常工作。我将把这个答案留给遇到这种情况的其他人。我仍然认为最好将Nginx用作实际部署的前端。