【问题标题】:Enable HTTP2 with Tomcat in Spring Boot在 Spring Boot 中使用 Tomcat 启用 HTTP2
【发布时间】: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


    【解决方案1】:

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

    【讨论】:

    • 这仅在使用 JDK 9 或更高版本时有效。我一直在尝试为在 docker 容器中运行的 spring boot 服务启用它,但它不起作用。在这里查看docs.spring.io/spring-boot/docs/current/reference/html/…
    • 它只是启用HTTP2,但application.yml中的任何配置都不会传递给Http2Protocol。除了 java 自我实现的配置,我找不到任何其他解决方案,它将 server.* 属性转发到 Http2Protocol。
    【解决方案2】:

    您需要将 HTTP 2 升级协议添加到 Tomcat 的连接器。您可以通过自定义嵌入式 Tomcat 容器来做到这一点:

    Java 8:

    @Bean
    public EmbeddedServletContainerCustomizer tomcatCustomizer() {
        return (container) -> {
            if (container instanceof TomcatEmbeddedServletContainerFactory) {
                ((TomcatEmbeddedServletContainerFactory) container)
                        .addConnectorCustomizers((connector) -> {
                    connector.addUpgradeProtocol(new Http2Protocol());
                });
            }
        };
    }
    

    Java 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());
                        }
    
                    });
                }
            }
    
        };
    }
    

    【讨论】:

    • 除了使用 https 运行 Tomcat 之外,还有什么需要做的吗? (我确实按照这个问题stackoverflow.com/questions/30404579/… 为本地主机启用了它)。但是在 Chrome 的网络调试器中,我看到一切仍然通过 http/1.1
    • h2c 将按原样工作,但没有多少(任何?)浏览器支持它。如果您希望它安全地工作 (h2),您需要使用 Tomcat Native 跳过一些障碍。
    • 寻求更多帮助的方式很奇怪。我已经完成了。
    • 只是补充一点,Tomcat 9 支持 HTTP2,并在 server.xml 文件中进行了一些配置。 readlearncode.com/configure-tomcat-9-for-http2
    • 我不能说没有更多信息。为什么不添加您自己的问题,提供尽可能多的信息?
    【解决方案3】:

    下面是使用 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”模式时遇到两个问题

    • 压缩不起作用,因为它依赖于 http 模式。所以后端必须照顾它
    • 后端看不到客户端的IP地址。可能我需要NAT。仍在调查中...

    一般来说,由于 haproxy 代理的是较低级别的 tcp 连接,因此无法访问任何 http 内容

    【讨论】:

    • 有没有办法不使用HAproxy? Spring boot 和 tomcat 不能只处理加密和升级?
    • 查看上面 Alex 发布的这个链接 readlearncode.com/configure-tomcat-9-for-http2
    • 我打算将它与 8.5 的 spring 嵌入式 tomcat 一起使用。我想我会试试 Undertow 它应该支持 http2
    • Embedded Tomcat 也支持 http2,ssl 可以这样配置:docs.spring.io/spring-boot/docs/current/reference/html/…。如果你这样做,并添加 connector.addUpgradeProtocol(new Http2Protocol());我相信它应该可以工作。
    • 你有关于嵌入式 tomcat (8.5) 支持 http2 的资料吗?我读了一些关于 tomcat native 的东西。我还不能设置tomcat。
    【解决方案4】:

    在 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
    

    【讨论】:

    • 值得注意的是,Spring Boot 2.0.x 使用的是 Tomcat 8.5,因此如果使用嵌入式 Tomcat,您仍然需要配置到 libtcnative 的路径,如 Spring Boot docs 中所述。 Spring Boot 2.1.x 将随 Tomcat 9 一起提供。
    【解决方案5】:

    Spring Boot 2.2.0+ 默认附带 Tomcat 9.0.x,当使用 JDK 9 或更高版本时,它支持开箱即用的 HTTP/2。 Link

    【讨论】:

      猜你喜欢
      • 2019-06-24
      • 2022-06-17
      • 1970-01-01
      • 1970-01-01
      • 2022-10-20
      • 2017-02-21
      • 2017-01-02
      • 1970-01-01
      • 2017-10-30
      相关资源
      最近更新 更多