简体   繁体   English

在 Spring Boot 中使用 Tomcat 启用 HTTP2

[英]Enable HTTP2 with Tomcat in Spring Boot

Tomcat 8.5 , which will be the default in Spring Boot 1.4 , supports HTTP/2 . Tomcat 8.5将成为Spring Boot 1.4 中的默认值,支持HTTP/2

How can HTTP/2 be enabled in a Spring Boot application?如何在Spring Boot应用程序中启用HTTP/2

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;
}

You need to add the HTTP 2 upgrade protocol to Tomcat's connector.您需要将 HTTP 2 升级协议添加到 Tomcat 的连接器中。 You can do that by customizing the embedded Tomcat container:您可以通过自定义嵌入式 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());
                    }

                });
            }
        }

    };
}

The most elegant and best-performing way to enable HTTP/2 with a Spring Boot application follows here.使用 Spring Boot 应用程序启用HTTP/2的最优雅、性能最好的方法如下。

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 (版本 >= 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.客户端将向 HAProxy 发送 https,而 HAProxy 将根据客户端的请求向后端发送明文 HTTP/1.1 或 HTTP/2。 There will be no unnecessary protocol translations.不会有不必要的协议转换。

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.压缩不起作用,因为它取决于模式 http。 So the backend has to take care of it所以后端必须照顾它
  • The backend can not see the client's IP-address.后端无法看到客户端的 IP 地址。 Probably I need NAT.可能我需要NAT。 Still investigating...还在调查中...

Generally, since haproxy proxies a lower level tcp connection, there is no access to any http stuff通常,由于 haproxy 代理较低级别的 tcp 连接,因此无法访问任何 http 内容

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-store-password=secret

Spring Boot 2.2.0+ ships by default with Tomcat 9.0.x which supports HTTP/2 out of the box when using JDK 9 or later. Spring Boot 2.2.0+ 默认随 Tomcat 9.0.x 一起提供,当使用 JDK 9 或更高版本时,Tomcat 9.0.x 支持开箱即用的 HTTP/2。 Link 链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM