java - with - tomcat embed spring boot




Abilita http2 con Tomcat in Spring Boot (3)

Tomcat 8.5 , che sarà il default in Spring Boot 1.4 , (che sarà rilasciato domani) supporta http2 .

Come può essere abilitato http2 in un'applicazione Spring Boot ?


È necessario aggiungere il protocollo di aggiornamento HTTP 2 al connettore di Tomcat. Puoi farlo personalizzando il contenitore Tomcat incorporato:

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

                });
            }
        }

    };
}

In Spring Boot 2 hai prima bisogno di un certificato - può essere generato in questo modo:

keytool -genkey -keyalg RSA -alias my-the-best-api -keystore c:\tmp\keystore.store -storepass secret -validity 3650 -keysize 2048

Quindi è sufficiente aggiungere questo certificato a classpath e aggiungere le proprietà necessarie a application.properties:

server.http2.enabled=true
server.port = 8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-password=secret

Qui segue il modo più elegante e più performante per abilitare HTTP/2 con un'applicazione Spring Boot.

Innanzitutto, come menzionato nella risposta di Andy Wilkinson, devi abilitare HTTP / 2 a livello di Tomcat:

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

Nel caso in cui non si utilizzi un Tomcat incorporato, è possibile impostare l'ascolto di HTTP / 2 in questo modo:

<Connector port="5080" protocol="HTTP/1.1" connectionTimeout="20000">
    <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
</Connector>

Ricorda che hai bisogno di Tomcat> = 8.5.

Quindi, dovresti usare HAProxy (versione> = 1.7) davanti a Tomcat per occuparti della crittografia.

Il client parlerà https a HAProxy e HAProxy pronuncerà cleartext HTTP / 1.1 o HTTP / 2 al backend, come richiesto dal cliente. Non ci saranno traduzioni di protocollo inutili.

La configurazione HAProxy corrispondente è qui:

# 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

Modifica 2019

Devo affrontare due problemi quando utilizzo la modalità "tcp"

  • La compressione non funziona, poiché dipende dalla modalità http. Quindi il back-end deve prendersene cura
  • Il back-end non può vedere l'indirizzo IP del client. Probabilmente ho bisogno di NAT. Ancora indagando ...

In generale, dal momento che haproxy proxy una connessione tcp di livello inferiore, non c'è accesso a qualsiasi materiale http





http2