HttpClientのタイムアウト

HttpClientタイムアウト

1. 概要

このチュートリアルでは、configure a timeout with the Apache HttpClient 4を実行する方法を示します。

深く掘り下げて、HttpClientでできる他のクールなことを学びたい場合は、the main HttpClient tutorialに進んでください。

参考文献:

HttpClient接続管理

Apache HttpClient 4との接続を開く、管理する、閉じる方法。

HttpClient 4 – POSTのリダイレクトに従う

Apache HttpClientでPOSTリダイレクトを有効にする方法。

高度なHttpClient設定

高度なユースケース向けのHttpClient構成。

2. 生のStringパラメータを介してタイムアウトを設定する

HttpClientには多くの構成パラメーターが付属しており、これらはすべて、一般的なマップのような方法で設定できます。

3 timeout parameters to configureがあります:

DefaultHttpClient httpClient = new DefaultHttpClient();

int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
httpParams.setParameter(
  CoreConnectionPNames.CONNECTION_TIMEOUT, timeout * 1000);
httpParams.setParameter(
  CoreConnectionPNames.SO_TIMEOUT, timeout * 1000);
httpParams.setParameter(
  ClientPNames.CONN_MANAGER_TIMEOUT, new Long(timeout * 1000));

3. APIを介してタイムアウトを構成する

これらのパラメータのうち、より重要なもの、つまり最初の2つは、よりタイプセーフなAPIを介して設定することもできます。

DefaultHttpClient httpClient = new DefaultHttpClient();

int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(
  httpParams, timeout * 1000); // http.connection.timeout
HttpConnectionParams.setSoTimeout(
  httpParams, timeout * 1000); // http.socket.timeout

3番目のパラメータにはHttpConnectionParamsにカスタムセッターがなく、setParameterメソッドを使用して手動で設定する必要があります。

4. 新しい4.3を使用したタイムアウトの構成。 ビルダー

4.3で導入された流暢なビルダーAPIは、the right way to set timeouts at a high levelを提供します。

int timeout = 5;
RequestConfig config = RequestConfig.custom()
  .setConnectTimeout(timeout * 1000)
  .setConnectionRequestTimeout(timeout * 1000)
  .setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client =
  HttpClientBuilder.create().setDefaultRequestConfig(config).build();

これは、タイプセーフで読み取り可能な方法で3つすべてのタイムアウトを構成するための推奨方法です。

5. タイムアウトプロパティの説明

それでは、これらのさまざまなタイプのタイムアウトの意味を説明しましょう。

  • Connection Timeouthttp.connection.timeout)–リモートホストとの接続を確立する時間

  • Socket Timeouthttp.socket.timeout)–データの待機時間–接続の確立後。 2つのデータパケット間の非アクティブの最大時間

  • Connection Manager Timeouthttp.connection-manager.timeout)–接続マネージャー/プールからの接続を待機する時間

最初の2つのパラメーター(接続とソケットのタイムアウト)が最も重要です。 ただし、接続を取得するためのタイムアウトを設定することは、高負荷のシナリオでは間違いなく重要です。そのため、3番目のパラメータを無視しないでください。

6. HttpClientの使用

設定後、クライアントを使用してHTTPリクエストを実行できるようになりました。

HttpGet getMethod = new HttpGet("http://host:8080/path");
HttpResponse response = httpClient.execute(getMethod);
System.out.println(
  "HTTP Status of response: " + response.getStatusLine().getStatusCode());

以前に定義されたクライアントの場合、the connection to the host will time out in 5 seconds.また、接続が確立されているがデータが受信されない場合、タイムアウトも5 additional secondsになります。

接続タイムアウトによりorg.apache.http.conn.ConnectTimeoutExceptionがスローされ、ソケットタイムアウトによりjava.net.SocketTimeoutExceptionがスローされることに注意してください。

7. ハードタイムアウト

HTTP接続を確立し、データを受信しないときにタイムアウトを設定すると非常に便利ですが、hard timeout for the entire requestを設定する必要がある場合があります。

たとえば、潜在的に大きなファイルのダウンロードはこのカテゴリに適合します。 この場合、接続が正常に確立され、データが一貫して送信されている可能性がありますが、操作が特定の時間しきい値を超えないようにする必要があります。

HttpClientには、リクエストの全体的なタイムアウトを設定できる構成がありません。ただし、abort functionality for requestsを提供するため、そのメカニズムを利用して単純なタイムアウトメカニズムを実装できます。

HttpGet getMethod = new HttpGet(
  "http://localhost:8080/httpclient-simple/api/bars/1");

int hardTimeout = 5; // seconds
TimerTask task = new TimerTask() {
    @Override
    public void run() {
        if (getMethod != null) {
            getMethod.abort();
        }
    }
};
new Timer(true).schedule(task, hardTimeout * 1000);

HttpResponse response = httpClient.execute(getMethod);
System.out.println(
  "HTTP Status of response: " + response.getStatusLine().getStatusCode());

java.util.Timerjava.util.TimerTaskを使用して、5秒のハードタイムアウト後にsimple delayed task which aborts the HTTP GET requestを設定しています。

8. タイムアウトとDNSラウンドロビン–注意すべき点

一部の大規模なドメインがDNSラウンドロビン構成を使用することは非常に一般的です-本質的にthe same domain mapped to multiple IP addressesを持ちます。 これにより、HttpClientがタイムアウトするそのドメインへの接続を試行する方法が理由で、そのようなドメインに対するタイムアウトの新しい課題が発生します。

  • HttpClientはそのドメインにthe list of IP routesを取得します

  • the first oneを試行します–タイムアウトします(設定したタイムアウトで)

  • the second oneを試行します–これもタイムアウトします

  • 等々 …

ご覧のとおり、the overall operation will not time out when we expect it toです。 代わりに、可能性のあるすべてのルートがタイムアウトになるとタイムアウトします。 さらに、これはクライアントに対して完全に透過的に行われます(ログがDEBUGレベルで構成されている場合を除く)。

この問題を実行して再現できる簡単な例を次に示します。

int timeout = 3;
RequestConfig config = RequestConfig.custom().
  setConnectTimeout(timeout * 1000).
  setConnectionRequestTimeout(timeout * 1000).
  setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client = HttpClientBuilder.create()
  .setDefaultRequestConfig(config).build();

HttpGet request = new HttpGet("http://www.google.com:81");
response = client.execute(request);

DEBUGログレベルの再試行ロジックに気付くでしょう。

DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.212:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator -
 Connect to www.google.com/173.194.34.212:81 timed out. Connection will be retried using another IP address

DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.208:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator -
 Connect to www.google.com/173.194.34.208:81 timed out. Connection will be retried using another IP address

DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.209:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator -
 Connect to www.google.com/173.194.34.209:81 timed out. Connection will be retried using another IP address
//...

9. 結論

このチュートリアルでは、HttpClientで使用可能なさまざまなタイプのタイムアウトを構成する方法について説明しました。 また、進行中のHTTP接続のハードタイムアウトの単純なメカニズムも示しました。

これらの例の実装は、the GitHub projectにあります。