web-dev-qa-db-ja.com

Apache HttpClientを使用して、リクエストとレスポンスにタイムアウトを設定する方法

サービス(Webサービスではない)に対して行うHttp要求のタイムアウトを設定する必要があります。 Apache HTTPクライアントを使用しています。これらの2行のコードを追加して、サービスに対する要求と応答のタイムアウトを設定しました。

HttpConnectionParams.setConnectionTimeout(params, 10000);
HttpConnectionParams.setSoTimeout(params, 10000);

1)現在、サービスからの応答がほぼ瞬時に表示されるため、タイムアウトとして10秒を設定しています。タイミングを増減する必要がありますか?

2)応答に10秒以上かかるとどうなりますか?例外をスローしますか?また、どの例外になりますか?以下のコードでタイムアウトを設定するために追加する必要があるものはありますか?.

public HashMap<String, Object> getJSONData(String url) throw Exception{
    DefaultHttpClient httpClient = new DefaultHttpClient();
    HttpParams params = httpClient.getParams();
    HttpConnectionParams.setConnectionTimeout(params, 10000);
    HttpConnectionParams.setSoTimeout(params, 10000);
    HttpHost proxy = new HttpHost(getProxy(), getProxyPort());
    ConnRouteParams.setDefaultProxy(params, proxy);
    URI uri;
    InputStream data = null;
    try {
        uri = new URI(url);
        HttpGet method = new HttpGet(uri);
        HttpResponse response = httpClient.execute(method);
        data = response.getEntity().getContent();
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    Reader r = new InputStreamReader(data);
    HashMap<String, Object> jsonObj = (HashMap<String, Object>) GenericJSONUtil.fromJson(r);
    return jsonObj;
}
35
pushya

表示される例外はConnectTimeoutExceptionSocketTimeoutExceptionです。実際に使用するタイムアウト値は、アプリケーションが待機できる最大時間である必要があります。読み取りタイムアウトに関する重要な注意事項の1つは、ソケット読み取りのタイムアウトに対応することです。したがって、完全な応答が到着するのに許可された時間ではなく、単一のソケット読み取りに与えられた時間です。したがって、それぞれ9秒かかる4つのソケット読み取りがある場合、合計読み取り時間は9 * 4 = 36秒です。

応答が到着するまでの合計時間(接続時間と合計読み取り時間を含む)を指定する場合は、呼び出しをスレッドでラップし、スレッドタイムアウトを使用できます。たとえば、私は通常このようなことをします:

Future<T> future = null;
future = pool.submit(new Callable<T>() {
    public T call() {
        return executeImpl(url);
    }   
}); 

try {
    return future.get(10, TimeUnit.SECONDS);
}   
catch (InterruptedException e) {
    log.warn("task interrupted", name);
}   
catch (ExecutionException e) {
    log.error(name + " execution exception", e); 
}   
catch (TimeoutException e) {
    log.debug("future timed out", name);
}

上記のコードで行われたいくつかの前提条件は次のとおりです。1)これはurlパラメーターを持つ関数内、2)名前変数を持つクラス内、3)ログはlog4jインスタンス、4)プールはスレッドプールエグゼキューターです。スレッドタイムアウトを使用する場合でも、HttpClientで接続タイムアウトとソケットタイムアウトも指定する必要があります。これにより、遅い要求がスレッドプール内のリソースを使い果たしてしまうことはありません。また、スレッドプールは多くのTomcatスレッドで共有されるように、通常はWebサービスで使用するため、スレッドプールを使用することに注意してください。あなたは環境が異なっているかもしれません、そして、あなたは単に呼び出しごとに新しいスレッドを生成したいかもしれません。

また、通常、次のように、paramsのメンバー関数を介してタイムアウトが設定されます。

params.setConnectionTimeout(10000);
params.setSoTimeout(10000);

ただし、構文も同様に機能する可能性があります(不明)。

35
Kevin

タイトルとHttpConnectionParams AP​​Iが廃止されたため、多くの人がここに来ると思います。

Apache HTTPクライアントの最新バージョンを使用して、リクエストパラメータを使用してこれらのタイムアウトを設定できます。

HttpPost request = new HttpPost(url);

RequestConfig requestConfig = RequestConfig.custom()
  .setSocketTimeout(TIMEOUT_MILLIS)
  .setConnectTimeout(TIMEOUT_MILLIS)
  .setConnectionRequestTimeout(TIMEOUT_MILLIS)
  .build();

request.setConfig(requestConfig);

または、HTTPクライアント用のビルダーAPIを使用してHTTPクライアントを作成するときにこれを設定することもできますが、カスタムソケット構成を使用してカスタム接続マネージャーを作成する必要もあります。

設定例ファイル は、Apache HTTPクライアントの設定方法を知るための優れたリソースです。

64
simao