HTTP / 2 in Jetty

1. Panoramica

Il protocollo HTTP / 2 viene fornito con una funzione push che consente al server di inviare più risorse al client per una singola richiesta . Quindi, migliora il tempo di caricamento della pagina riducendo i molteplici round trip necessari per recuperare tutte le risorse.

Jetty supporta il protocollo HTTP / 2 sia per le implementazioni client che server.

In questo tutorial, esploreremo il supporto HTTP / 2 in Jetty e creeremo un'applicazione web Java per esaminare la funzionalità Push HTTP / 2.

2. Introduzione

2.1. Download di Jetty

Jetty richiede JDK 8 o versione successiva e il supporto ALPN (Application-Layer Protocol Negotiation) per l'esecuzione di HTTP / 2.

In genere, il server Jetty viene distribuito su SSL e abilita il protocollo HTTP / 2 tramite l'estensione TLS (ALPN) .

Innanzitutto, dovremo scaricare l'ultima distribuzione di Jetty e impostare la variabile JETTY_HOME .

2.2. Abilitazione del connettore HTTP / 2

Successivamente, possiamo utilizzare un comando Java per abilitare il connettore HTTP / 2 sul server Jetty:

java -jar $JETTY_HOME/start.jar --add-to-start=http2

Questo comando aggiunge il supporto del protocollo HTTP / 2 al connettore SSL sulla porta 8443 . Inoltre, abilita transitivamente il modulo ALPN per la negoziazione del protocollo:

INFO : server transitively enabled, ini template available with --add-to-start=server INFO : alpn-impl/alpn-1.8.0_131 dynamic dependency of alpn-impl/alpn-8 INFO : alpn-impl transitively enabled INFO : alpn transitively enabled, ini template available with --add-to-start=alpn INFO : alpn-impl/alpn-8 dynamic dependency of alpn-impl INFO : http2 initialized in ${jetty.base}/start.ini INFO : ssl transitively enabled, ini template available with --add-to-start=ssl INFO : threadpool transitively enabled, ini template available with --add-to-start=threadpool INFO : bytebufferpool transitively enabled, ini template available with --add-to-start=bytebufferpool INFO : Base directory was modified

Qui, i log mostrano le informazioni di moduli come ssl e alpn-impl / alpn-8 che sono abilitati transitivamente per il connettore HTTP / 2.

2.3. Avvio di Jetty Server

Ora siamo pronti per avviare il server Jetty:

java -jar $JETTY_HOME/start.jar

All'avvio del server, la registrazione mostrerà i moduli abilitati:

INFO::main: Logging initialized @228ms to org.eclipse.jetty.util.log.StdErrLog ... INFO:oejs.AbstractConnector:main: Started [email protected]{SSL, (ssl, alpn, h2)}{0.0.0.0:8443} INFO:oejs.Server:main: Started @872ms

2.4. Abilitazione di moduli aggiuntivi

Allo stesso modo, possiamo abilitare altri moduli come http e http2c :

java -jar $JETTY_HOME/start.jar --add-to-start=http,http2c

Verifichiamo i log:

INFO:oejs.AbstractConnector:main: Started [email protected]{SSL, (ssl, alpn, h2)}{0.0.0.0:8443} INFO:oejs.AbstractConnector:main: Started [email protected]{HTTP/1.1, (http/1.1, h2c)}{0.0.0.0:8080} INFO:oejs.Server:main: Started @685ms

Inoltre, possiamo elencare tutti i moduli forniti da Jetty:

java -jar $JETTY_HOME/start.jar --list-modules

L'output sarà simile a:

Available Modules: ================== tags: [-internal] Modules for tag '*': -------------------- Module: alpn : Enables the ALPN (Application Layer Protocol Negotiation) TLS extension. Depend: ssl, alpn-impl LIB: lib/jetty-alpn-client-${jetty.version}.jar LIB: lib/jetty-alpn-server-${jetty.version}.jar XML: etc/jetty-alpn.xml Enabled: transitive provider of alpn for http2 // ... Modules for tag 'connector': ---------------------------- Module: http2 : Enables HTTP2 protocol support on the TLS(SSL) Connector, : using the ALPN extension to select which protocol to use. Tags: connector, http2, http, ssl Depend: ssl, alpn LIB: lib/http2/*.jar XML: etc/jetty-http2.xml Enabled: ${jetty.base}/start.ini // ... Enabled Modules: ================ 0) alpn-impl/alpn-8 dynamic dependency of alpn-impl 1) http2 ${jetty.base}/start.ini // ...

2.5. Configurazione aggiuntiva

Simile all'argomento –list-modules , possiamo usare –list-config per elencare tutti i file di configurazione XML per ogni modulo:

java -jar $JETTY_HOME/start.jar --list-config

Per configurare le proprietà comuni come host e porta per il server Jetty, possiamo apportare modifiche nel file start.ini :

jetty.ssl.host=0.0.0.0 jetty.ssl.port=8443 jetty.ssl.idleTimeout=30000

Inoltre, ci sono alcune proprietà http2 come maxConcurrentStreams e maxSettingsKeys che possiamo configurare:

jetty.http2.maxConcurrentStreams=128 jetty.http2.initialStreamRecvWindow=524288 jetty.http2.initialSessionRecvWindow=1048576 jetty.http2.maxSettingsKeys=64 jetty.http2.rateControl.maxEventsPerSecond=20

3. Configurazione di un'applicazione Jetty Server

3.1. Configurazione Maven

Ora che abbiamo configurato Jetty, è il momento di creare la nostra applicazione.

Aggiungiamo il plug-in Maven jetty-maven- plugin al nostro pom.xml insieme alle dipendenze Maven come http2-server , jetty-alpn-openjdk8-server e jetty-servlet :

 org.eclipse.jetty jetty-maven-plugin 9.4.27.v20200227 org.eclipse.jetty.http2 http2-server 9.4.27.v20200227 org.eclipse.jetty jetty-alpn-openjdk8-server 9.4.27.v20200227 org.eclipse.jetty jetty-servlets 9.4.27.v20200227 

Quindi, compileremo le classi usando il comando Maven:

mvn clean package

Infine, possiamo distribuire la nostra app Maven non assemblata al server Jetty:

mvn jetty:run-forked

Per impostazione predefinita, il server si avvia sulla porta 8080 con il protocollo HTTP / 1.1:

oejmp.Starter:main: Started Jetty Server oejs.AbstractConnector:main: Started [email protected]{HTTP/1.1, (http/1.1)}{0.0.0.0:8080} oejs.Server:main: Started @1045ms

3.2. Configura HTTP / 2 in jetty.xml

Successivamente, configureremo il server Jetty con il protocollo HTTP / 2 nel nostro file jetty.xml aggiungendo l' elemento Call appropriato :

 alpn h2 8444 

Here, the HTTP/2 connector is configured with ALPN on port 8444 along with sslContextFactory and httpConfig configs.

Also, we can add other modules like h2-17 and h2-16 (draft versions of h2) by defining comma-separated arguments in jetty.xml:

 h2,h2-17,h2-16 

Then, we'll configure the location of the jetty.xml in our pom.xml:

 org.eclipse.jetty jetty-maven-plugin 9.4.27.v20200227 8888 quit -Xbootclasspath/p: ${settings.localRepository}/org/mortbay/jetty/alpn/alpn-boot/8.1.11.v20170118/alpn-boot-8.1.11.v20170118.jar ${basedir}/src/main/config/jetty.xml / ... 

Note: To enable HTTP/2 in our Java 8 app, we've added the alpn-boot jar to the JVM BootClasspath. However, ALPN support is already available in Java 9 or later.

Let's re-compile our classes and re-run the application to verify if the HTTP/2 protocol is enabled:

oejmp.Starter:main: Started Jetty Server oejs.AbstractConnector:main: Started [email protected]{SSL, (ssl, http/1.1)}{0.0.0.0:8443} oejs.AbstractConnector:main: Started [email protected]{SSL, (ssl, alpn, h2)}{0.0.0.0:8444}

Here, we can observe that port 8443 is configured with the HTTP/1.1 protocol and 8444 with HTTP/2.

3.3. Configure the PushCacheFilter

Next, we need a filter that pushes the secondary resources like images, JavaScript, and CSS to the client.

To do so, we can use the PushCacheFilter class available in the org.eclipse.jetty.servlets package. PushCacheFilter builds a cache of secondary resources associated with a primary resource like index.html and pushes them to the client.

Let's configure the PushCacheFilter in our web.xml:

 push org.eclipse.jetty.servlets.PushCacheFilter ports 8444 push /* 

3.4. Configure Jetty Servlet and Servlet Mapping

Then, we'll create the Http2JettyServlet class to access the images, and we'll add the servlet-mapping in our web.xml file:

 http2Jetty com.baeldung.jetty.http2.Http2JettyServlet http2Jetty /images/* 

4. Setting up the HTTP/2 Client

Finally, to verify the HTTP/2 Push feature and the improved page-load time, we'll create an http2.html file that loads a few images (secondary resources):

 Baeldung HTTP/2 Client in Jetty 

HTTP/2 Demo

5. Testing the HTTP/2 Client

To get a baseline for the page-load time, let's access the HTTP/1.1 application at //localhost:8443/http2.html with the Developer Tools to verify the protocol and load time:

Here, we can observe that the images are loaded in 3-6ms using the HTTP/1.1 protocol.

Then, we'll access the HTTP/2 application, which has Push enabled, at //localhost:8444/http2.html:

Here, we observe that the protocol is h2, the initiator is Push, and the loading time is 1ms for all the images (secondary resources).

Therefore, the PushCacheFilter caches the secondary resources for http2.html, pushes them on port 8444, and provides a great improvement in the load time of the page.

6. Conclusion

In this tutorial, we've explored HTTP/2 in Jetty.

First, we examined how to start Jetty with the HTTP/2 protocol along with its configurations.

Then, we've seen a Java 8 web application with the HTTP/2 Push feature, configured with a PushCacheFilter, and observed how the load time of a page containing secondary resources improved over what we saw with the HTTP/1.1 protocol.

As usual, all the code implementations are available over on GitHub.