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 http2
be enabled in a Spring Boot
application?
如何http2
在Spring Boot
应用程序中启用?
采纳答案by yglodt
The most elegant and best-performing way to enable HTTP/2
with 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