1.概要


AsyncHttpClient

(AHC)は、リンク:/netty[Netty]の上に構築されたライブラリで、HTTP要求を簡単に実行し、応答を非同期に処理することができます。

この記事では、HTTPクライアントの構成方法と使用方法、要求の実行方法とAHCを使用した応答の処理方法について説明します。

2.セットアップ

ライブラリの最新版はhttps://mvnrepository.com/artifact/org.asynchttpclient/async-http-client[Maven repository]にあります。

com.ningのグループIDではなく、グループID

org.asynchttpclient__の依存関係を使用するように注意してください。

<dependency>
    <groupId>org.asynchttpclient</groupId>
    <artifactId>async-http-client</artifactId>
    <version>2.2.0</version>
</dependency>

3. HTTPクライアントの設定

HTTPクライアントを取得する最も直接的な方法は、

Dsl

クラスを使用することです。静的な

asyncHttpClient()メソッドは、

AsyncHttpClient__オブジェクトを返します。

AsyncHttpClient client = Dsl.asyncHttpClient();

HTTPクライアントのカスタム設定が必要な場合は、ビルダー

DefaultAsyncHttpClientConfig.Builder

を使用して

AsyncHttpClient

オブジェクトを構築できます。

DefaultAsyncHttpClientConfig.Builder clientBuilder = Dsl.config()

これにより、タイムアウト、プロキシサーバー、HTTP証明書などを設定することができます。

DefaultAsyncHttpClientConfig.Builder clientBuilder = Dsl.config()
  .setConnectTimeout(500)
  .setProxyServer(new ProxyServer(...));
AsyncHttpClient client = Dsl.asyncHttpClient(clientBuilder);

HTTPクライアントのインスタンスを設定して取得すると、アプリケーション全体で再利用できます。内部的に新しいスレッドと接続プールが作成されるため、リクエストごとにインスタンスを作成する必要はありません。これはパフォーマンスの問題につながります。

また、** クライアントの使用が終わったら、

close()

メソッドを呼び出してメモリリークやリソースの停止を防ぐ必要があることにも注意してください。

4. HTTPリクエストを作成する

AHCを使ってHTTPリクエストを定義する方法は2つあります。

  • バウンド

  • 未バインド

パフォーマンスに関して、2つの要求タイプに大きな違いはありません。これらは、リクエストを定義するために使用できる2つの別々のAPIを表しているだけです。 ** バインドされたリクエストは、それが作成されたHTTPクライアントに結び付けられており、特に指定がなければ、デフォルトでその特定のクライアントの設定を使用します。

たとえば、バインドされたリクエストを作成するときはHTTPクライアント設定から

disableUrlEncoding

フラグが読み込まれますが、バインドされていないリクエストの場合はデフォルトでfalseに設定されます。 VM引数として渡されたシステムプロパティを使用することで、アプリケーション全体を再コンパイルせずにクライアント設定を変更できるため、これは便利です。

java -jar -Dorg.asynchttpclient.disableUrlEncodingForBoundRequests=true

プロパティの完全なリストは

ahc-default.properties

ファイルにあります。

4.1. バウンドリクエスト

バインドされたリクエストを作成するために、接頭辞

“ prepare”

で始まるクラス

AsyncHttpClient

からのヘルパーメソッドを使用します。また、作成済みの

Request

オブジェクトを受け取る__prepareRequest()メソッドを使用することもできます。

たとえば、

prepareGet()

メソッドはHTTP GETリクエストを作成します。

BoundRequestBuilder getRequest = client.prepareGet("http://www.baeldung.com");

4.2. 未バインド要求


RequestBuilder

クラスを使用して、バインドされていないリクエストを作成できます。

Request getRequest = new RequestBuilder(HttpConstants.Methods.GET)
  .setUrl("https://www.baeldung.com")
  .build();

または

Dsl

ヘルパークラスを使用して、実際にはHTTPメソッドとリクエストのURLを設定するために

RequestBuilder

を使用します。

Request getRequest = Dsl.get("http://www.baeldung.com").build()

5. HTTPリクエストを実行する

ライブラリの名前は、要求を実行する方法についてのヒントを与えてくれます。 AHCは、同期要求と非同期要求の両方をサポートしています。

要求の実行はその種類によって異なります。

バウンドリクエストを使用するときは

BoundRequestBuilder


クラスの

execute()

メソッドを使用し、

アンバウンドリクエストがあるときは

AsyncHttpClient

インターフェース

のexecuteRequest()メソッドの実装の1つを使用してそれを実行します。

5.1. 同期的に

このライブラリは非同期になるように設計されていますが、必要に応じて

Future

オブジェクトをブロックすることで同期呼び出しをシミュレートできます。

execute()

メソッドと

executeRequest()

メソッドはどちらも

ListenableFuture <Response>

オブジェクトを返します。このクラスはJavaの

Future

インタフェースを拡張し、HTTP要求が完了して応答を返すまで現在のスレッドをブロックするために使用できる__get()メソッドを継承します。

Future<Response> responseFuture = boundGetRequest.execute();
responseFuture.get();

Future<Response> responseFuture = client.executeRequest(unboundRequest);
responseFuture.get();

同期呼び出しを使用してコードの一部をデバッグしようとすると便利ですが、非同期実行によってパフォーマンスとスループットが向上する本番環境での使用はお勧めできません。

5.2. 非同期に

非同期実行について説明するときには、結果を処理するためのリスナーについても説明します。 AHCライブラリは、非同期HTTP呼び出しに使用できる3種類のリスナーを提供します。


  • AsyncHandler


  • AsyncCompletionHandler


  • ListenableFuture

    リスナー


AsyncHandler

リスナーは、完了する前にHTTP呼び出しを制御および処理する可能性を提供します。これを使用すると、HTTP呼び出しに関連する一連のイベントを処理できます。

request.execute(new AsyncHandler<Object>() {
    @Override
    public State onStatusReceived(HttpResponseStatus responseStatus)
      throws Exception {
        return null;
    }

    @Override
    public State onHeadersReceived(HttpHeaders headers)
      throws Exception {
        return null;
    }

    @Override
    public State onBodyPartReceived(HttpResponseBodyPart bodyPart)
      throws Exception {
        return null;
    }

    @Override
    public void onThrowable(Throwable t) {

    }

    @Override
    public Object onCompleted() throws Exception {
        return null;
    }
});


State

enumはHTTPリクエストの処理を制御することを可能にします。


State.ABORT

を返すことで、特定の瞬間に処理を停止することができます


  • AsyncHandler

    はスレッドセーフではないため、同時要求を実行するときには再利用しないでください。


AsyncCompletionHandler

は、

AsyncHandler

インターフェースからすべてのメソッドを継承し、呼び出し完了を処理するための

onCompleted(Response)

ヘルパーメソッドを追加します。他のすべてのリスナーメソッドは、


_State .

_

CONTINUEを返すようにオーバーライドされているため、コードが読みやすくなります。

request.execute(new AsyncCompletionHandler<Object>() {
    @Override
    public Object onCompleted(Response response) throws Exception {
        return response;
    }
});


ListenableFuture

インターフェースを使用すると、HTTP呼び出しが完了したときに実行されるリスナーを追加できます。

また、リスナーからのコードを別のスレッドプールを使用して実行します。

ListenableFuture<Response> listenableFuture = client
  .executeRequest(unboundRequest);
listenableFuture.addListener(() -> {
    Response response = listenableFuture.get();
    LOG.debug(response.getStatusCode());
}, Executors.newCachedThreadPool());

その上、リスナーを追加するオプションである

ListenableFuture

インターフェースは、

Future

レスポンスを

CompletableFuture

に変換することを可能にします。

7.まとめ

AHCは非常に強力なライブラリで、おもしろい機能がたくさんあります。これは、HTTPクライアントと同期要求と非同期要求の両方を実行する機能を構成するための非常に簡単な方法を提供します。

いつものように、この記事のソースコードはhttps://github.com/eugenp/tutorials/tree/master/libraries[over GitHub]から入手できます。