我有一个
angular
Web 应用程序,它使用 Spring boot 并在后端嵌入了 tomcat
服务器。我想让已建立的 http 连接保持更长时间,以提高后续 http 请求的响应时间。使用 http/1.1
,浏览器被告知通过添加 Connection: Keep-Alive
和类似 Keep-Alive: timeout=5, max=1000
到 response header
来保持 http 连接处于活动状态。但是,HTTP/2 中禁止连接特定的标头字段,例如 Connection 和 Keep-Alive 。因此,Chrome 和 Firefox 在 HTTP/2 响应中忽略它们。对于 HTTP/2,特定于连接的元数据应该通过其他方式传送。
我在任何地方都找不到那些“其他手段”应该是什么。我也无法在任何地方找到如何配置嵌入式 Tomcat 9 服务器以将
Keep-alive
元数据添加到 HTTP/2
响应。这就是现在 tomcat 的配置方式:
@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatCustomizer() {
return (tomcat) -> tomcat.addConnectorCustomizers((connector) -> {
if (connector.getProtocolHandler() instanceof AbstractHttp11Protocol) {
AbstractHttp11Protocol<?> protocolHandler = (AbstractHttp11Protocol<?>) connector
.getProtocolHandler();
protocolHandler.setDisableUploadTimeout(false);
protocolHandler.setConnectionUploadTimeout(5000);
protocolHandler.setKeepAliveTimeout(4000);
protocolHandler.setMaxKeepAliveRequests(200);
protocolHandler.setUseKeepAliveResponseHeader(true);
}
});
}
但是如果我想使用
HTTP/2
,这些设置将不起作用。有什么想法吗?
使用 http/1.1,浏览器被告知通过在响应标头中添加 Connection: Keep-Alive 和 Keep-Alive: timeout=5, max=1000 等内容来保持 http 连接处于活动状态。
事实并非如此。自 HTTP/1.1 起,除非明确设置为
Connection: Keep-Alive
,否则 Close
标头默认为这种情况。事实上,我们甚至拥有的标头更多是 HTTP/1.0 时代遗留下来的,不需要设置。响应始终更多地说明服务器将做什么,而不是向客户端发出指令(“嘿,仅供参考,我将使用这些设置”),但由于服务器(和客户端),它总是毫无意义。如果它也愿意的话,可以断开连接。一般来说,如果一台服务器的 TCP 连接耗尽,它不应该真正保留未使用的旧连接,而应该接受新连接。
但是,HTTP/2 中禁止连接特定的标头字段,例如 Connection 和 Keep-Alive。因此,Chrome 和 Firefox 在 HTTP/2 响应中忽略它们。对于 HTTP/2,应通过其他方式传送特定于连接的元数据。
我在任何地方都找不到那些“其他手段”应该是什么。我也无法在任何地方找到如何配置嵌入式 Tomcat 9 服务器以将 Keep-alive 元数据添加到 HTTP/2 响应。这就是现在 tomcat 的配置方式:
与之前一样,HTTP/2 只是去掉了毫无意义的标头,并假设您希望保持它的活性。它在 HTTP/2 中也没有什么意义,因为它用于多个请求和响应,而 HTTP/1.1 一次仅用于一个,并且保持活动状态是一种连接级别设置。因此,如果 HTTP/2 请求可以指定
keep-alive: close
,这对于该连接上已经进行中的其他请求意味着什么?同样,将其设置为 keep-alive
是由 HTTP/2 多路复用的本质所暗示的。
由客户端和服务器根据自己的逻辑和资源限制来决定何时最好断开连接,尽管 HTTP/2 规范稍后会继续说明这一点:
HTTP/2 连接是持久的。为了获得最佳性能,预计客户端不会关闭连接,直到确定不需要与服务器进行进一步通信(例如,当用户离开特定网页时)或直到服务器关闭连接。