我整天都在与这个非常奇怪的问题作斗争。这是我非常简单的控制器方法:
@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。但是我希望把它推迟到以后。
答案 0 :(得分:1)
我目前对 Http2Protocol
有类似的错误。向servlet上传数据时,连接中途关闭。当我返回一个字节数组时,Chrome 有时会返回消息 ERR_HTTP2_PROTOCOL_ERROR
,并且大部分时间它都可以工作。这只是偶尔发生,但在生产使用中非常烦人。
它还只是帮助我从配置中删除了 HTTP/2
,默认情况下未设置 keepAliveTimeout
。
答案 1 :(得分:0)
我想我明白了。我不知道keepAliveTimeout在里面做什么,但是我把它拿出来,然后再次测试就可以了。然后,我将字节数组的大小增加到100mb,并且可以正常工作。我将把这个答案留给遇到这种情况的其他人。我仍然认为最好将Nginx用作实际部署的前端。