52

次のコードを使用して、サーバーにリクエストを送信しようとしています。常に3回目のリクエストで失敗しました。

import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

public class HttpClientTest {
    private HttpClient client;

    public HttpClientTest() {
        HttpParams params = new BasicHttpParams();
        params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 15000);  
        params.setParameter(CoreConnectionPNames.SO_TIMEOUT, 15000);

        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, "utf-8");
        HttpProtocolParams.setUseExpectContinue(params, true);
        ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager();
        cm.setMaxTotal(100);
        client = new DefaultHttpClient(cm, params);

        while (true) {
            HttpPost mPost = new HttpPost("http://myip/myservice");

            JSONObject json = new JSONObject();
            try {
                json.put("serialNumber", "abcd");
            } catch (JSONException e1) {
                e1.printStackTrace();
            }
            StringEntity s = null;
            try {
                s = new StringEntity(json.toString());
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }               
            s.setContentEncoding("UTF-8");
            s.setContentType("application/json");
            mPost.setEntity(s);

            JSONObject response = null;

            System.out.println("HttpClientTest ---> send post");
            HttpResponse mHttpResponse;
            try {
                mHttpResponse = client.execute(mPost);
                System.out.println("HttpClientTest  ---> get response");
                if(mHttpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                    HttpEntity entity = mHttpResponse.getEntity(); 
                    ContentType contentType = ContentType.getOrDefault(entity);
                    Charset charset = contentType.getCharset();
                    response = new JSONObject(new JSONTokener(new InputStreamReader(entity.getContent(), charset)));

                    System.out.println("HttpClientTest ---> get result:" + response.toString());
                } else {
                    mPost.abort();
                    break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        HttpClientTest t = new HttpClientTest();
    }
}

次のような例外:

org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection
    at org.apache.http.impl.conn.tsccm.ConnPoolByRoute.getEntryBlocking(ConnPoolByRoute.java:417)
    at org.apache.http.impl.conn.tsccm.ConnPoolByRoute$1.getPoolEntry(ConnPoolByRoute.java:300)
    at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager$1.getConnection(ThreadSafeClientConnManager.java:224)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:401)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732)
    at com.i360r.client.takeaway.network.HttpClientTest.<init>(HttpClientTest.java:68)
    at com.i360r.client.takeaway.network.HttpClientTest.main(HttpClientTest.java:88)
4

10 に答える 10

76

私は同じ問題を抱えていて、修正を見つけました。このタイムアウトは、接続リークが原因です。私の場合、httpDeleteメソッドを使用しており、応答を消費していません。代わりに、応答のステータスを確認しています。

修正は、応答エンティティを使用する必要があることです。システム リソースを適切に解放するには、エンティティに関連付けられているコンテンツ ストリームを閉じる必要があります。

そこで EntityUtils.consumeQuietly(response.getEntity());、エンティティ コンテンツが完全に消費され、コンテンツ ストリームが存在する場合は閉じられるようにする方法を使用しました。

于 2014-04-02T20:17:48.570 に答える
35

私はそれを修正しました!ブロックで追加mPost.releaseConnection()します。finally

 try {
 } catch (Exception e) {
 } finally {
  mPost.releaseConnection();
 }

パッケージorg.apache.httpcomponentsを 4.2.1 に更新してください

于 2012-08-09T23:13:55.383 に答える
8

応答を取得する行を try-with-resources 内に配置し、次のように HttpResponse の代わりに CloseableHttpResponse を使用します。

try(final CloseableHttpResponse mHttpResponse = client.execute(mPost);)
{
 System.out.println("HttpClientTest  ---> get response");
 ....remainder code

mHttpResponse オブジェクトは自動的に消費され、閉じられます

お役に立てれば!

于 2018-04-03T15:27:51.587 に答える
3

ApacheHttpClientこれは、DropWizard 0.6.2を使用している場合にも発生する可能性があります。DropWizard 0.6.2 は、バックグラウンドでMultiThreadedHttpConnectionManager既定の構成で を作成します。その既定の構成では、一度に 2 つの同時 http 接続しか許可されません。詳細については、こちらを参照してください

したがって、この構成では、サーバーが混雑して常に同じホストにリクエストを行っている場合、一度に最大 2 つの接続を実行できます。

于 2016-11-17T19:47:28.993 に答える
1

spark を介して寄木細工を読み書きするときに、このエラーが発生していました。正確なエラーは次のとおりです:
com.amazonaws.SdkClientException: HTTP リクエストを実行できません: プールからの接続を待機中のタイムアウト

最終的に、これは Hadoop のバージョン 3.1.3 へのアップグレードに関連していることがわかりました。

この新しいバージョンの Hadoop では、プロパティ名が
fs.s3a.connection.maximum
から
spark.hadoop.fs.s3aに変更されたようです。 .connection.maximum Spark

構成でプロパティの名前を変更すると、元に戻ります。

于 2020-01-20T06:42:27.850 に答える
0

私の場合、エンティティ コンテンツ ストリームを消費していた bufferedReader が閉じられていませんでした。閉じるとエラーが解決しました。

于 2020-04-09T19:21:48.680 に答える