web-dev-qa-db-ja.com

HttpClientが例外なくスタックした

私は、ApacheのHttpClientを多用する長期実行アプリケーションを開発しています。

最初のテスト実行では、アプリケーションはスタックするまで完全に機能しました。それは停止されず、例外をスローしませんでした。そこに座って何もしていません。

ちょうど今、2回目のランニングをして、時間を止めました。 24時間の一定稼働。さらに、私が実行していた私のラップトップのインターネット接続が、アプリケーションがスタックしたちょうどその瞬間に終了したことに気付きました。ネットを再度実行するには、WLANアダプターを再起動する必要がありました。

ただし、接続が再び確立した後、アプリケーションは動作に戻りませんでした。そして今、再び行き詰まっている。

HttpClientで知らないタイムアウトコントローラはありますか?接続がダウンしているときにアプリケーションが例外をスローしないのはなぜですか?

クライアントを使用する部分は次のようになります。

_public HttpUtil(ConfigUtil config) {
    this.config = config;

    client = new DefaultHttpClient();
    client.getParams().setParameter(HttpProtocolParams.USER_AGENT, this.config.getProperty("httputil.userAgent"));
}

public String getContentAsString(String url) throws ParseException, ClientProtocolException, IOException {
    return EntityUtils.toString(
            client.execute(
                    new HttpGet(url)).getEntity());
}
_

アプリケーションは、必要なURLでhttputil.getContentAsString()を繰り返し呼び出します。

25
F.P

このコードは廃止されました(HttpParamsなどを取得)。より良い方法は:

RequestConfig defaultRequestConfig = RequestConfig.custom()
    .setCookieSpec(CookieSpecs.BEST_MATCH)
    .setExpectContinueEnabled(true)
    .setStaleConnectionCheckEnabled(true)
    .setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST))
    .setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC))
    .build();

HttpGet httpGet = new HttpGet(url);    
RequestConfig requestConfig = RequestConfig.copy(defaultRequestConfig)
    .setSocketTimeout(5000)
    .setConnectTimeout(5000)
    .setConnectionRequestTimeout(5000)
    .build();
httpGet.setConfig(requestConfig);
12
Manish Patel

バージョン4.4以降、ユーザーuser2393012とStephen Cによる回答はどちらも非推奨になりました。別の方法があるかどうかはわかりませんが、私が行う方法はビルダーパラダイムであるHTTPClientBuilderを使用することです。

例.

HttpClients.custom().setConnectionTimeToLive(1, TimeUnit.MINUTES).build()

OPの説明と非常によく似た(実際にはOPの問題であった可能性があります)問題も発生しますが、Apacheがデフォルトの同時接続をクライアントごとに2つの接続のみに設定しているためです。これに対する解決策は、最大接続数を増やすか、可能であればそれらを閉じることです。

最大接続数を増やすには:

HttpClients.custom().setMaxConnPerRoute(100000).build()

接続を閉じるには、BasicHttpClientConnectionManagerを使用して、closeメソッドを呼び出すことができます。

8
Muhatashim

使用しているHttpClientのバージョンはまだ言っていませんが、バージョン4であると仮定すると、 このブログ記事 は何をすべきかを説明しています。

DefaultHttpClient httpClient = new DefaultHttpClient();
HttpParams params = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(httpParams, connectionTimeoutMillis);
HttpConnectionParams.setSoTimeout(httpParams, socketTimeoutMillis);
6
Stephen C

私は別のスレッドで同様の答えを出しました( HttpClientはメソッドが正常に実行され、socketRead0でハングします

私の場合、リクエストでconnectionTimeoutとsocketTimeoutを設定していましたが、SSL接続の確立中に使用された接続ソケットでは設定していませんでした。その結果、SSLハンドシェイク中にハングアップすることがありました。以下は、v4.4(v4.5でもテスト済み)を使用して3つすべてのタイムアウトを設定するコードです。

// Configure the socket timeout for the connection, incl. ssl tunneling
connManager = new PoolingHttpClientConnectionManager();
connManager.setMaxTotal(200);
connManager.setDefaultMaxPerRoute(100);

SocketConfig sc = SocketConfig.custom()
    .setSoTimeout(soTimeoutMs)
    .build();

connManager.setDefaultSocketConfig(sc);

HttpClient client = HttpClients.custom()
            .setConnectionManager(connManager)
            .setConnectionManagerShared(true)
            .build();

// configure the timeouts (socket and connection) for the request
RequestConfig.Builder config = = RequestConfig.copy(RequestConfig.DEFAULT);
config.setConnectionRequestTimeout(connectionTimeoutMs);
config.setSocketTimeout(socketTimeoutMs);

HttpRequestBase req = new HttpGet(uri);
req.setConfig(config.build());

client.execute(req);
5
GaspardP

私はすべてのタイムアウトをうまく設定していますが、httpチャンクを実行するが結果を送信しないurlを使用していることがわかりました(chromeでは正常に動作しますが、httpクライアントではタイムアウトを設定しても永久にハングします)。幸い、私はサーバーを所有していて、ゴミを返すだけで、ハングしなくなりました。これは、httpクライアントがなんらかの空のチャンクケースを適切に処理しないという非常にユニークなバグのようです(私はかなり離れている可能性があります)。 httpチャンクcsvがhttpクライアントにダウンロードされます。

4
Dean Hiller

同じ問題があり、DefaultHttpClientを閉じなかったためにスタックしました。
これは間違っています:

try{
    DefaultHttpClient httpclient = new DefaultHttpClient();
    ...
} catch (Exception e){
    e.PrintStackTrace();
}

そして、これは正しいです:

try (DefaultHttpClient httpclient = new DefaultHttpClient()){
    ...
} catch (Exception e){
    e.PrintStackTrace();
}

それが誰かを助けることを願っています。

4
Max Husiv

デフォルトでは、HttpClientはタイムアウトしません(これにより、問題が発生しやすくなります)。ハードウェアの問題である可能性があります。ネットワークアダプターが停止すると、HttpClientがハングします。

以下は Parameters に設定 HttpParams コンストラクタの一部として DefaultHttpClient を含む

http.socket.timeout:ソケットタイムアウト(SO_TIMEOUT)をミリ秒単位で定義します。これは、データを待機するためのタイムアウトであり、言い換えると、最大期間です2つの連続するデータパケット間の非アクティブ)。ゼロのタイムアウト値は、無限タイムアウトとして解釈されます。このパラメーターには、タイプJava.lang.Integerの値が必要です。このパラメーターが設定されていない場合、読み取り操作はタイムアウトしません(無限タイムアウト)。

これは接続にタイムアウトを設定するため、設定されたタイムアウトの後、例外がスローされます。

3
mguymon