Java 在 Spring Boot 中使用 Tomcat 启用 http2
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38612704/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Enable http2 with Tomcat in Spring Boot
提问by yglodt
Tomcat 8.5, which will be the default in Spring Boot 1.4, (to be released tomorrow) supports http2.
Tomcat 8.5,这将是Spring Boot 1.4,(明天发布)中的默认支持http2。
How can http2be enabled in a Spring Bootapplication?
如何http2在Spring Boot应用程序中启用?
采纳答案by yglodt
The most elegant and best-performing way to enable HTTP/2with a Spring Boot application follows here.
HTTP/2使用 Spring Boot 应用程序启用的最优雅、性能最佳的方法如下。
First, as mentioned in Andy Wilkinson's answer, you need to enable HTTP/2 at Tomcat level:
首先,正如安迪威尔金森的回答中提到的,您需要在 Tomcat 级别启用 HTTP/2:
@Bean
public EmbeddedServletContainerCustomizer tomcatCustomizer() {
return (container) -> {
if (container instanceof TomcatEmbeddedServletContainerFactory) {
((TomcatEmbeddedServletContainerFactory) container)
.addConnectorCustomizers((connector) -> {
connector.addUpgradeProtocol(new Http2Protocol());
});
}
};
}
In case you are not using an embedded Tomcat, you can set up HTTP/2 listening like this:
如果您没有使用嵌入式 Tomcat,您可以像这样设置 HTTP/2 侦听:
<Connector port="5080" protocol="HTTP/1.1" connectionTimeout="20000">
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
</Connector>
Remember that you need Tomcat >= 8.5.
请记住,您需要 Tomcat >= 8.5。
Then, you should use HAProxy(version >= 1.7)in front of Tomcat to take care of encryption.
然后,您应该在 Tomcat 前面使用HAProxy(version >= 1.7)来处理加密。
The client will speak https to HAProxy, and HAProxy will speak cleartext HTTP/1.1 or HTTP/2 to the backend, as the client requested. There will be no unnecessary protocol translations.
客户端将向 HAProxy 发送 https,而 HAProxy 将根据客户端的请求向后端发送明文 HTTP/1.1 或 HTTP/2。不会有不必要的协议转换。
The matching HAProxy-configuration is here:
匹配的 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
Edit 2019
编辑 2019
I face two problems when using mode "tcp"
使用模式“tcp”时我面临两个问题
- Compression does not work, since it depends on mode http. So the backend has to take care of it
- The backend can not see the client's IP-address. Probably I need NAT. Still investigating...
- 压缩不起作用,因为它取决于模式 http。所以后端必须照顾它
- 后端无法看到客户端的 IP 地址。可能我需要NAT。还在调查中...
Generally, since haproxy proxies a lower level tcp connection, there is no access to any http stuff
通常,由于 haproxy 代理较低级别的 tcp 连接,因此无法访问任何 http 内容
回答by Andy Wilkinson
You need to add the HTTP 2 upgrade protocol to Tomcat's connector. You can do that by customizing the embedded Tomcat container:
您需要将 HTTP 2 升级协议添加到 Tomcat 的连接器。您可以通过自定义嵌入式 Tomcat 容器来实现:
Java 8:
爪哇 8:
@Bean
public EmbeddedServletContainerCustomizer tomcatCustomizer() {
return (container) -> {
if (container instanceof TomcatEmbeddedServletContainerFactory) {
((TomcatEmbeddedServletContainerFactory) container)
.addConnectorCustomizers((connector) -> {
connector.addUpgradeProtocol(new Http2Protocol());
});
}
};
}
Java 7:
爪哇7:
@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());
}
});
}
}
};
}
回答by Mahozad
In Spring Boot 2.1 and above it is as simple as adding this property to your .properties (or .yml) file:
在 Spring Boot 2.1 及更高版本中,只需将此属性添加到您的 .properties(或 .yml)文件中即可:
server.http2.enabled=true
You can also do it programmatically like this (in one of your configuration classes):
您也可以像这样以编程方式执行此操作(在您的配置类之一中):
@Bean
public ConfigurableServletWebServerFactory tomcatCustomizer() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.addConnectorCustomizers(connector -> connector.addUpgradeProtocol(new Http2Protocol()));
return factory;
}
回答by Jozef Najman
In Spring Boot 2 you first need a certificate - it can by generated like this:
在 Spring Boot 2 中,您首先需要一个证书 - 它可以像这样生成:
keytool -genkey -keyalg RSA -alias my-the-best-api -keystore c:\tmp\keystore.store -storepass secret -validity 3650 -keysize 2048
Than you just need to add this certificate to classpath and add needed properties to application.properties:
比您只需要将此证书添加到类路径并将所需的属性添加到 application.properties:
server.http2.enabled=true
server.port = 8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-password=secret

