1. 概要

HTTP / 2 プロトコルには、サーバーが1つのリクエストに対して複数のリソースをクライアントに送信できるようにするプッシュ機能が付属しています。 したがって、すべてのリソースをフェッチするために必要な複数のラウンドトリップを減らすことにより、ページの読み込み時間を改善します。

Jetty は、クライアントとサーバーの両方の実装でHTTP/2プロトコルをサポートします。

このチュートリアルでは、JettyでのHTTP / 2サポートについて説明し、Java Webアプリケーションを作成して、 HTTP/2プッシュ機能を調べます。

2. 入門

2.1. Jettyのダウンロード

Jettyには、HTTP / 2を実行するために、JDK8以降とALPN (アプリケーション層プロトコルネゴシエーション)のサポートが必要です。

通常、 JettyサーバーはSSLを介してデプロイされ、TLS拡張(ALPN)を介してHTTP/2プロトコルを有効にします。

まず、最新の Jetty ディストリビューションをダウンロードし、JETTY_HOME変数を設定する必要があります。

2.2. HTTP/2コネクタを有効にする

次に、Javaコマンドを使用して、JettyサーバーでHTTP/2コネクタを有効にします。

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

このコマンドは、ポート8443のSSLコネクタにHTTP/2プロトコルサポートを追加します。 また、プロトコルネゴシエーションのためにALPNモジュールを一時的に有効にします。

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

ここで、ログには、HTTP/2コネクタに対して一時的に有効になっているsslalpn-impl/alpn-8などのモジュールの情報が表示されます。

2.3. Jettyサーバーの起動

これで、Jettyサーバーを起動する準備が整いました。

java -jar $JETTY_HOME/start.jar

サーバーが起動すると、ログには有効になっているモジュールが表示されます。

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

2.4. 追加モジュールの有効化

同様に、httphttp2cなどの他のモジュールを有効にすることができます。

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

ログを確認しましょう:

INFO:oejs.AbstractConnector:main: Started ServerConnector@6adede5{SSL, (ssl, alpn, h2)}{0.0.0.0:8443}
INFO:oejs.AbstractConnector:main: Started ServerConnector@dc24521{HTTP/1.1, (http/1.1, h2c)}{0.0.0.0:8080}
INFO:oejs.Server:main: Started @685ms

また、Jettyが提供するすべてのモジュールを一覧表示できます。

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

出力は次のようになります。

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. 追加の構成

–list-modules 引数と同様に、 –list-config を使用して、各モジュールのすべてのXML構成ファイルを一覧表示できます。

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

Jettyサーバーのhostportなどの共通プロパティを構成するには、start.iniファイルに変更を加えることができます。

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

また、maxConcurrentStreamsmaxSettingsKeysなど、構成できるhttp2プロパティがいくつかあります。

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

3. Jettyサーバーアプリケーションのセットアップ

3.1. Maven構成

Jettyを構成したので、次はアプリケーションを作成します。

jetty-maven-plugin Mavenプラグインを、 http2-server jetty-alpn-openjdk8などのMaven依存関係とともに、pom.xmlに追加しましょう。 -server 、および jetty-servlets

<build>
    <plugins>
        <plugin>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-maven-plugin</artifactId>
            <version>9.4.27.v20200227</version>
            <dependencies>
                <dependency>
                    <groupId>org.eclipse.jetty.http2</groupId>
                    <artifactId>http2-server</artifactId>
                    <version>9.4.27.v20200227</version>
                </dependency>
                <dependency>
                    <groupId>org.eclipse.jetty</groupId>
                    <artifactId>jetty-alpn-openjdk8-server</artifactId>
                    <version>9.4.27.v20200227</version>
                </dependency>
                <dependency>
                    <groupId>org.eclipse.jetty</groupId>
                    <artifactId>jetty-servlets</artifactId>
                    <version>9.4.27.v20200227</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

次に、Mavenコマンドを使用してクラスをコンパイルします。

mvn clean package

そして最後に、アセンブルされていないMavenアプリをJettyサーバーにデプロイできます。

mvn jetty:run-forked

デフォルトでは、サーバーはHTTP/1.1プロトコルを使用してポート8080で起動します。

oejmp.Starter:main: Started Jetty Server
oejs.AbstractConnector:main: Started ServerConnector@4d910fd6{HTTP/1.1, (http/1.1)}{0.0.0.0:8080}
oejs.Server:main: Started @1045ms

3.2. jetty.xmlでHTTP/2を構成します

次に、適切な Call 要素を追加して、jetty.xmlファイルでHTTP/2プロトコルを使用してJettyサーバーを構成します。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
<Configure id="Server" class="org.eclipse.jetty.server.Server">
    <!-- sslContextFactory and httpConfig configs-->

    <Call name="addConnector">
        <Arg>
            <New class="org.eclipse.jetty.server.ServerConnector">
                <Arg name="server"><Ref id="Server"/></Arg>
                <Arg name="factories">
                    <Array type="org.eclipse.jetty.server.ConnectionFactory">
                        <Item>
                            <New class="org.eclipse.jetty.server.SslConnectionFactory">
                                <Arg name="sslContextFactory"><Ref id="sslContextFactory"/></Arg>
                                <Arg name="next">alpn</Arg>
                            </New>
                        </Item>
                        <Item>
                            <New class="org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory">
                                <Arg>h2</Arg>
                            </New>
                        </Item>
                        <Item>
                            <New class="org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory">
                                <Arg name="config"><Ref id="httpConfig"/></Arg>
                            </New>
                        </Item>
                    </Array>
                </Arg>
                <Set name="port">8444</Set>
            </New>
        </Arg>
    </Call>

    <!-- other Call elements -->
</Configure>

ここで、HTTP / 2コネクターは、ポート 8444 のALPNと、sslContextFactoryおよびhttpConfig構成で構成されています。

また、 jettyでカンマ区切りの引数を定義することにより、h2-17h2-16 h2 のドラフトバージョン)などの他のモジュールを追加できます。 .xml

<Item> 
    <New class="org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory"> 
        <Arg>h2,h2-17,h2-16</Arg> 
    </New> 
</Item>

次に、pom.xmljetty.xmlの場所を構成します。

<plugin>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <version>9.4.27.v20200227</version>
    <configuration>
        <stopPort>8888</stopPort>
        <stopKey>quit</stopKey>
        <jvmArgs>
            -Xbootclasspath/p:
            ${settings.localRepository}/org/mortbay/jetty/alpn/alpn-boot/8.1.11.v20170118/alpn-boot-8.1.11.v20170118.jar
        </jvmArgs>
        <jettyXml>${basedir}/src/main/config/jetty.xml</jettyXml>
        <webApp>
            <contextPath>/</contextPath>
        </webApp>
    </configuration>
    ...
</plugin>

注:Java8アプリでHTTP/ 2を有効にするために、alpn-bootjarをJVMBootClasspathに追加しました。 ただし、ALPNサポートはJava9以降ですでに利用可能です。

クラスを再コンパイルし、アプリケーションを再実行して、HTTP/2プロトコルが有効になっているかどうかを確認しましょう。

oejmp.Starter:main: Started Jetty Server
oejs.AbstractConnector:main: Started ServerConnector@6fadae5d{SSL, (ssl, http/1.1)}{0.0.0.0:8443}
oejs.AbstractConnector:main: Started ServerConnector@1810399e{SSL, (ssl, alpn, h2)}{0.0.0.0:8444}

ここでは、ポート8443がHTTP/1.1プロトコルで構成され、8444がHTTP/2で構成されていることがわかります。

3.3. PushCacheFilterを構成します

次に、画像、JavaScript、CSSなどの二次リソースをクライアントにプッシュするフィルターが必要です。

そのために、org.eclipse.jetty.servletsパッケージで利用可能なPushCacheFilterクラスを使用できます。 PushCacheFilter は、 index.html などのプライマリリソースに関連付けられたセカンダリリソースのキャッシュを構築し、それらをクライアントにプッシュします。

web.xmlPushCacheFilterを構成しましょう。

<filter>
    <filter-name>push</filter-name>
    <filter-class>org.eclipse.jetty.servlets.PushCacheFilter</filter-class>
    <init-param>
        <param-name>ports</param-name>
        <param-value>8444</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>push</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

3.4. Jettyサーブレットとサーブレットマッピングの構成

次に、画像にアクセスするための Http2JettyServlet クラスを作成し、web.xmlファイルにservlet-mappingを追加します。

<servlet>
    <servlet-name>http2Jetty</servlet-name>
    <servlet-class>com.baeldung.jetty.http2.Http2JettyServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>http2Jetty</servlet-name>
    <url-pattern>/images/*</url-pattern>
</servlet-mapping>

4. HTTP/2クライアントのセットアップ

最後に、HTTP / 2プッシュ機能と改善されたページ読み込み時間を確認するために、いくつかの画像(セカンダリリソース)を読み込むhttp2.htmlファイルを作成します。

<!DOCTYPE html>
<html>
<head>
    <title>Baeldung HTTP/2 Client in Jetty</title>
</head>
<body>
    <h2>HTTP/2 Demo</h2>
    <div>
        <img src="images/homepage-latest_articles.jpg" alt="latest articles" />
        <img src="images/homepage-rest_with_spring.jpg" alt="rest with spring" />
        <img src="images/homepage-weekly_reviews.jpg" alt="weekly reviews" />
    </div>
</body>
</html>

5. HTTP/2クライアントのテスト

ページ読み込み時間のベースラインを取得するには、開発者ツールを使用して https:// localhost:8443 /http2.htmlでHTTP/1.1アプリケーションにアクセスし、プロトコルと読み込み時間を確認します。

 

ここでは、HTTP / 1.1プロトコルを使用して、画像が3〜6ミリ秒で読み込まれることを確認できます。

次に、 https:// localhost:8444 /http2.htmlでプッシュが有効になっているHTTP/2アプリケーションにアクセスします。

 

 

ここでは、プロトコルが h2 、イニシエーターが Push 、すべての画像(セカンダリリソース)の読み込み時間が1msであることがわかります。

したがって、 PushCacheFilter http2.htmlのセカンダリリソースをキャッシュし、はそれらをポート 8444 にプッシュし、ページの読み込み時間を大幅に改善します。

6. 結論

このチュートリアルでは、JettyのHTTP/2について説明しました。

最初に、HTTP/2プロトコルとその構成を使用してJettyを起動する方法を検討しました。

次に、PushCacheFilterで構成されたHTTP/2プッシュ機能を備えたJava8Webアプリケーションを確認し、セカンダリリソースを含むページの読み込み時間がHTTP/1.1プロトコル。

いつものように、すべてのコード実装はGitHub利用できます。