HTTP / 1.1がリリースされてから16年後、IETFは2015年にようやくHTTP / 2プロトコルに合格しました。HTTP / 2プロトコルは、待ち時間を短縮し、現在の時代の情報応答時間の要件を満たすように設計されています。この記事では、HTTP / 2プロトコルを簡単に紹介し、次にJava9のHTTP / 2とそのHTTPクライアントAPIのサポートの変更点の調査に焦点を当てます。
1. HTTP / 2の概要
- HTTP / 2は、HTTP / 1.1によって引き起こされる問題を軽減し、複雑なインフラストラクチャを良好なパフォーマンスで維持するように設計されています。HTTP / 2は引き続きHTTP / 1.1と下位互換性がありますが、テキストベースのプロトコルではなくなりました。
- HTTP / 2多重化により、単一の接続で複数の双方向ストリームを処理できるため、クライアントは単一の接続を介して複数のリソースを同時にダウンロードできます。
- HTTP 1.xプロトコルはテキストベースであるため、メッセージは非常に冗長です。同じHTTPヘッダーのセットが何度も交換されることがあります。HTTP / 2は、リクエスト間でHTTPヘッダーを維持し、繰り返されるデータ交換を排除し、データの相互作用に必要な帯域幅を大幅に削減します。
HTTP / 2データプッシュ
HTTP / 2サーバー側のデータプッシュはWebSocketの継続またはアップグレードであると思われるかもしれませんが、そうではありません。WebSocketsは、クライアントとサーバー間の全二重通信の方法であり、サーバーはTCP接続の確立後にデータをクライアントに送信しますが、HTTP / 2は別のソリューションを提供します。
HTTP / 2プッシュは、クライアントの観点からリソース要求を開始することなく、クライアントにリソースをアクティブに送信することです。これは、サーバーが要求に基づいてWebサイトでさらに必要な他のリソースを認識し、クライアントが再度要求するずっと前にすべてのリソースを(事前に)一緒に送信できることを意味します。
現在HTTP / 2をサポートしているJavaHTTPクライアント
- 桟橋
- Netty
- OkHttp
- Vert.x
- ホタル
ただし、この記事では、これらのJavaクライアントソフトウェアではなく、Java9によって提供されるHTTP / 2サポートについて説明します。
2. Java9用のHTTP / 2クライアント
まず、Java9構文を使用してモジュールをインポートします。jdk.incubator.httpclient
module com.springui.echo.client {
requires jdk.incubator.httpclient;
}
Java9の新しいHTTPCient APIは、ビルダーパターンに従います。HttpClientは、HTTPリクエストを操作するために使用されるエントリポイントであり、最初に構築されてから使用されます。
HttpClient client = HttpClient
.newBuilder()
.version(Version.HTTP_2) //支持HTTP2
.build();
ブロッキングモードでリクエストを送信する
HttpClientインスタンスを取得したら、それを使用してHttpRequestを送信できます。また、コンストラクターを使用してHttpRequestインスタンスを作成することもできます。
HttpResponse<String> response = client.send(
HttpRequest
.newBuilder(TEST_URI) //请求地址
.POST(BodyProcessor.fromString("Hello world")) //POST报文数据
.build(),
BodyHandler.asString() //请求响应数据处理,接收字符串
);
リクエストが送信された後、スレッドはレスポンスデータが取得されるまでブロックします。これはJAVA8以前のHTTPAPIと同じです。ただし、Java 9には、非同期の非ブロッキング送信を使用して要求を処理する方法が用意されています。これは、高度な同時HTTP要求と処理に適しています。
非ブロッキングモードでリクエストを送信する(Java 9)
以下の例では、10個のランダムな整数が非同期で送信されます。
List<CompletableFuture<String>> responseFutures =
IntStream.of(1,2,3,4,5,6,7,8,9,10) //10个整数形成IntStream,Java 8的语法
.mapToObj(String::valueOf) //10个整数转换成字符串,Java 8的语法
.map(message -> client.sendAsync( //将10个整数字符串作为内容,发送10个异步请求
HttpRequest.newBuilder(TEST_URI)
.POST(HttpRequest.BodyProcessor.fromString(message))
.build(),
HttpResponse.BodyHandler.asString()
).thenApply(HttpResponse::body) //以CompletableFuture<HttpResponse.body()>作为流处理的返回值
)
.collect(Collectors.toList()); //将Stream转成List
上記の例では、多くのJava 8 Stream APIを使用しています。慣れていない場合は、以前に書いた記事を読むことができます。sendAsyncメソッドの戻り値は、以降の処理にCompletableFuture<HttpResponse<String>>
使用されthenApply(HttpResponse::body)
、最終的な戻り値はCompletableFuture<String>
です。CompletableFutureは、同時非同期処理の結果を出力するJava非同期プログラミングの知識です。
responseFutures.stream().forEach(future -> {
LOGGER.info("Async response: " + future.getNow(null));
});
すべてのリクエストが非同期で送信され、結果が返されるため、最終的な印刷ログが1、2、3、4、5、6、7、8、9、10の順序で処理されない場合があります。非同期処理に使用されたCompletableFutureの結果。
3.HTTP2をサポートするプッシュプロミスフレーム
上記の例はすべてHTTP / 1.1プロトコルで完了できますが、新しいノンブロッキング非同期APIが追加され、HTTP / 2機能は含まれていません。心配しないでください。最も緊密に統合されたJava9クライアントAPIとHTTP / 2は、HTTP2を使用してリクエストを送信し、複数の非同期データ結果を取得できることです。(もちろん、一部のデータは事前にプッシュされます。これには、サーバーが連携のためにHTTP / 2もサポートする必要があります)
Map<HttpRequest,CompletableFuture<HttpResponse<String>>> responses =
client.sendAsync( //注意这里只发送一次请求
HttpRequest.newBuilder(TEST_URI)
.POST(HttpRequest.BodyProcessor.fromString(TEST_MESSAGE))
.build(),
HttpResponse.MultiProcessor.asMap( //多个资源的响应结果
request -> Optional.of(HttpResponse.BodyHandler.asString())
)
).join();
responses.forEach((request, responseFuture) -> {
LOGGER.info("Async response: " + responseFuture.getNow(null));
});
Java 9の観点からは、新しいHTTP / 2クライアントAPIは見栄えがします。ただ、現在の関連技術の使い方はあまり成熟していないと思いますので、とりあえず試してみてはいかがでしょうか。
私のブログをフォローすることを歓迎します、多くのブティックコレクションがあります
- この記事は、出典を示して複製されています(接続を添付する必要があり、テキストのみを複製することはできません):レターブラザーのブログ。
あなたがそれがあなたに役立つと思うなら、私のためにそれを好きにして共有してください!あなたのサポートは私の尽きることのない創造的な動機です!。また、最近、以下のような高品質なコンテンツを出力しておりますので、よろしくお願いいたします。