【发布时间】:2023-03-05 10:51:01
【问题描述】:
Tomcat 8.5,将是 Spring Boot 1.4 中的默认设置,支持 HTTP/2。
如何在 Spring Boot 应用程序中启用 HTTP/2?
【问题讨论】:
标签: java spring-boot http tomcat http2
Tomcat 8.5,将是 Spring Boot 1.4 中的默认设置,支持 HTTP/2。
如何在 Spring Boot 应用程序中启用 HTTP/2?
【问题讨论】:
标签: java spring-boot http tomcat http2
在Spring Boot 2.1 and above 中,只需将此属性添加到您的.properties(或.yml)文件中即可:
server.http2.enabled=true
您也可以像这样以编程方式执行此操作(在您的配置类之一中):
@Bean
public ConfigurableServletWebServerFactory tomcatCustomizer() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.addConnectorCustomizers(connector -> connector.addUpgradeProtocol(new Http2Protocol()));
return factory;
}
【讨论】:
您需要将 HTTP 2 升级协议添加到 Tomcat 的连接器。您可以通过自定义嵌入式 Tomcat 容器来做到这一点:
@Bean
public EmbeddedServletContainerCustomizer tomcatCustomizer() {
return (container) -> {
if (container instanceof TomcatEmbeddedServletContainerFactory) {
((TomcatEmbeddedServletContainerFactory) container)
.addConnectorCustomizers((connector) -> {
connector.addUpgradeProtocol(new Http2Protocol());
});
}
};
}
@Bean
public EmbeddedServletContainerCustomizer tomcatCustomizer() {
return new EmbeddedServletContainerCustomizer() {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
if (container instanceof TomcatEmbeddedServletContainerFactory) {
((TomcatEmbeddedServletContainerFactory) container)
.addConnectorCustomizers(new TomcatConnectorCustomizer() {
@Override
public void customize(Connector connector) {
connector.addUpgradeProtocol(new Http2Protocol());
}
});
}
}
};
}
【讨论】:
h2c 将按原样工作,但没有多少(任何?)浏览器支持它。如果您希望它安全地工作 (h2),您需要使用 Tomcat Native 跳过一些障碍。
下面是使用 Spring Boot 应用程序启用 HTTP/2 的最优雅、性能最好的方法。
首先,正如 Andy Wilkinson 的回答中提到的,您需要在 Tomcat 级别启用 HTTP/2:
@Bean
public EmbeddedServletContainerCustomizer tomcatCustomizer() {
return (container) -> {
if (container instanceof TomcatEmbeddedServletContainerFactory) {
((TomcatEmbeddedServletContainerFactory) container)
.addConnectorCustomizers((connector) -> {
connector.addUpgradeProtocol(new Http2Protocol());
});
}
};
}
如果你没有使用嵌入式 Tomcat,你可以像这样设置 HTTP/2 监听:
<Connector port="5080" protocol="HTTP/1.1" connectionTimeout="20000">
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
</Connector>
记住您需要 Tomcat >= 8.5。
那么,你应该在Tomcat前面使用HAProxy(version >= 1.7)来处理加密。
客户端将向 HAProxy 发送 https,HAProxy 将根据客户端的请求向后端发送明文 HTTP/1.1 或 HTTP/2。 不会有不必要的协议翻译。
匹配的 HAProxy 配置在这里:
# Create PEM: cat cert.crt cert.key ca.crt > /etc/ssl/certs/cert.pem
global
tune.ssl.default-dh-param 2048
ssl-default-bind-options no-sslv3 no-tls-tickets force-tlsv12
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
chroot /var/lib/haproxy
user haproxy
group haproxy
defaults
timeout connect 10000ms
timeout client 60000ms
timeout server 60000ms
frontend fe_https
mode tcp
rspadd Strict-Transport-Security:\ max-age=31536000;\ includeSubDomains;\ preload
rspadd X-Frame-Options:\ DENY
bind *:443 ssl crt /etc/ssl/certs/cert.pem alpn h2,http/1.1
default_backend be_http
backend be_http
mode tcp
server domain 127.0.0.1:8080
# compression algo gzip # does not work in mode "tcp"
# compression type text/html text/css text/javascript application/json
编辑 2019
使用“tcp”模式时遇到两个问题
一般来说,由于 haproxy 代理的是较低级别的 tcp 连接,因此无法访问任何 http 内容
【讨论】:
在 Spring Boot 2 中,您首先需要一个证书 - 它可以像这样生成:
keytool -genkey -keyalg RSA -alias my-the-best-api -keystore c:\tmp\keystore.store -storepass secret -validity 3650 -keysize 2048
您只需将此证书添加到类路径并将所需的属性添加到 application.properties:
server.http2.enabled=true
server.port = 8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=secret
【讨论】:
libtcnative 的路径,如 Spring Boot docs 中所述。 Spring Boot 2.1.x 将随 Tomcat 9 一起提供。
Spring Boot 2.2.0+ 默认附带 Tomcat 9.0.x,当使用 JDK 9 或更高版本时,它支持开箱即用的 HTTP/2。 Link
【讨论】: