HTTP / 2 im Steg

1. Übersicht

Das HTTP / 2-Protokoll verfügt über eine Push-Funktion, mit der der Server mehrere Ressourcen für eine einzelne Anforderung an den Client senden kann . Daher wird die Ladezeit der Seite verbessert, indem die mehrfachen Roundtrips reduziert werden, die zum Abrufen aller Ressourcen erforderlich sind.

Jetty unterstützt das HTTP / 2-Protokoll sowohl für Client- als auch für Server-Implementierungen.

In diesem Tutorial werden wir die HTTP / 2-Unterstützung in Jetty untersuchen und eine Java-Webanwendung erstellen, um die HTTP / 2-Push-Funktion zu untersuchen.

2. Erste Schritte

2.1. Anlegestelle herunterladen

Jetty erfordert JDK 8 oder höher und ALPN-Unterstützung (Application-Layer Protocol Negotiation) für die Ausführung von HTTP / 2.

In der Regel wird der Jetty-Server über SSL bereitgestellt und aktiviert das HTTP / 2-Protokoll über die TLS-Erweiterung (ALPN) .

Zuerst müssen wir die neueste Jetty-Distribution herunterladen und die Variable JETTY_HOME festlegen .

2.2. Aktivieren des HTTP / 2-Connectors

Als Nächstes können wir einen Java-Befehl verwenden, um den HTTP / 2-Connector auf dem Jetty-Server zu aktivieren:

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

Dieser Befehl fügt dem SSL-Connector an Port 8443 Unterstützung für das HTTP / 2-Protokoll hinzu . Außerdem wird das ALPN-Modul transitiv für die Protokollverhandlung aktiviert:

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

Hier zeigen die Protokolle die Informationen von Modulen wie ssl und alpn-impl / alpn-8 , die für den HTTP / 2-Connector transitiv aktiviert sind.

2.3. Jetty Server starten

Jetzt können wir den Jetty-Server starten:

java -jar $JETTY_HOME/start.jar

Wenn der Server gestartet wird, werden in der Protokollierung die aktivierten Module angezeigt:

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. Zusätzliche Module aktivieren

Ebenso können wir andere Module wie http und http2c aktivieren :

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

Lassen Sie uns die Protokolle überprüfen:

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

Außerdem können wir alle von Jetty bereitgestellten Module auflisten:

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

Die Ausgabe sieht folgendermaßen aus:

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. Zusätzliche Konfiguration

Ähnlich wie beim Argument –list-modules können wir –list-config verwenden, um alle XML-Konfigurationsdateien für jedes Modul aufzulisten :

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

Um die allgemeinen Eigenschaften wie Host und Port für den Jetty-Server zu konfigurieren , können Sie Änderungen an der Datei start.ini vornehmen :

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

Außerdem gibt es einige http2- Eigenschaften wie maxConcurrentStreams und maxSettingsKeys , die wir konfigurieren können:

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

3. Einrichten einer Jetty Server-Anwendung

3.1. Maven-Konfiguration

Nachdem wir Jetty konfiguriert haben, ist es Zeit, unsere Anwendung zu erstellen.

Wir wollen die Anlegestelle-maven-Plugin Maven Plugin unsere pom.xml zusammen mit Maven Abhängigkeiten wie http2-Server , Anlegestelle-ALPN-openjdk8-Server und Anlegesteg-Servlets :

 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 

Dann kompilieren wir die Klassen mit dem Befehl Maven:

mvn clean package

Und schließlich können wir unsere nicht zusammengebaute Maven-App auf dem Jetty-Server bereitstellen:

mvn jetty:run-forked

Standardmäßig startet der Server an Port 8080 mit dem HTTP / 1.1-Protokoll:

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. Konfigurieren Sie HTTP / 2 in jetty.xml

Als Nächstes konfigurieren wir den Jetty-Server mit dem HTTP / 2-Protokoll in unserer Datei jetty.xml , indem wir das entsprechende Call- Element hinzufügen :

 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.