HTTP / 2 di Jetty

1. Ikhtisar

Protokol HTTP / 2 hadir dengan fitur push yang memungkinkan server mengirim banyak sumber daya ke klien untuk satu permintaan . Karenanya, ini meningkatkan waktu muat halaman dengan mengurangi beberapa perjalanan bolak-balik yang diperlukan untuk mengambil semua sumber daya.

Jetty mendukung protokol HTTP / 2 untuk implementasi klien dan server.

Dalam tutorial ini, kita akan menjelajahi dukungan HTTP / 2 di Jetty dan membuat aplikasi web Java untuk memeriksa fitur HTTP / 2 Push.

2. Memulai

2.1. Mendownload Jetty

Jetty memerlukan JDK 8 atau yang lebih baru dan dukungan ALPN (Application-Layer Protocol Negotiation) untuk menjalankan HTTP / 2.

Biasanya, server Jetty digunakan melalui SSL dan mengaktifkan protokol HTTP / 2 melalui ekstensi TLS (ALPN) .

Pertama, kita perlu mengunduh distribusi Jetty terbaru dan menyetel variabel JETTY_HOME .

2.2. Mengaktifkan Konektor HTTP / 2

Selanjutnya, kita dapat menggunakan perintah Java untuk mengaktifkan konektor HTTP / 2 di server Jetty:

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

Perintah ini menambahkan dukungan protokol HTTP / 2 ke konektor SSL pada port 8443 . Selain itu, ini secara transitif mengaktifkan modul ALPN untuk negosiasi protokol:

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

Di sini, log menampilkan informasi modul seperti ssl dan alpn-impl / alpn-8 yang secara transitif diaktifkan untuk konektor HTTP / 2.

2.3. Memulai Server Jetty

Sekarang, kami siap untuk memulai server Jetty:

java -jar $JETTY_HOME/start.jar

Saat server dimulai, pencatatan akan menampilkan modul yang diaktifkan:

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. Mengaktifkan Modul Tambahan

Demikian pula, kami dapat mengaktifkan modul lain seperti http dan http2c :

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

Mari verifikasi 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

Juga, kami dapat membuat daftar semua modul yang disediakan oleh Jetty:

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

Outputnya akan terlihat seperti:

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. Konfigurasi Tambahan

Mirip dengan argumen –list-modules , kita dapat menggunakan –list-config untuk membuat daftar semua file konfigurasi XML untuk setiap modul:

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

Untuk mengkonfigurasi properti umum seperti host dan port untuk server Jetty, kita dapat membuat perubahan di file start.ini :

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

Juga, ada beberapa http2 properti seperti maxConcurrentStreams dan maxSettingsKeys bahwa kita dapat mengkonfigurasi:

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

3. Menyiapkan Aplikasi Server Jetty

3.1. Konfigurasi Maven

Sekarang setelah Jetty dikonfigurasi, sekarang saatnya membuat aplikasi kita.

Mari tambahkan plugin Maven jetty-maven-plugin ke pom.xml bersama dengan dependensi Maven seperti http2-server , jetty-alpn-openjdk8-server , dan jetty-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 

Kemudian, kami akan mengkompilasi kelas menggunakan perintah Maven:

mvn clean package

Dan terakhir, kami dapat menerapkan aplikasi Maven kami yang belum dirakit ke server Jetty:

mvn jetty:run-forked

Secara default, server dimulai pada port 8080 dengan protokol 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. Konfigurasi HTTP / 2 di jetty.xml

Selanjutnya, kita akan mengkonfigurasi server Jetty dengan protokol HTTP / 2 di file jetty.xml kita dengan menambahkan elemen Call yang sesuai :

 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.