40

サービス (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;
}
4

2 に答える 2

75

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

最近のバージョンの 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 クライアントの設定方法を知るための優れたリソースです。

于 2015-07-01T11:19:31.353 に答える
36

表示される例外はConnectTimeoutExceptionSocketTimeoutExceptionです。使用する実際のタイムアウト値は、アプリケーションが待機できる最大時間でなければなりません。読み取りタイムアウトに関する重要な注意事項の 1 つは、ソケット読み取りのタイムアウトに対応することです。したがって、完全な応答が到着するまでに許容される時間ではなく、1 つのソケットの読み取りに与えられる時間です。したがって、4 つのソケット読み取りがあり、それぞれに 9 秒かかる場合、合計読み取り時間は 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 で接続とソケットのタイムアウトも指定する必要があることに注意してください。これにより、遅い要求によってスレッド プール内のリソースが消費されなくなります。また、スレッド プールを使用していることにも注意してください。これは、通常、スレッド プールを Web サービスで使用するため、スレッド プールが一連の Tomcat スレッド間で共有されるためです。環境が異なる場合があり、呼び出しごとに新しいスレッドを単純に生成することを好む場合があります。

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

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

しかし、おそらくあなたの構文も同様に機能します(確かではありません)。

于 2012-03-26T14:21:12.467 に答える