Подтвердить что ты не робот

Исключение httpclient "org.apache.http.conn.ConnectionPoolTimeoutException: ожидания ожидания соединения"

Я пытаюсь отправить запрос на свой сервер со следующим кодом. он всегда выполнялся при третьем запросе.

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)
4b9b3361

Ответ 1

У меня была такая же проблема, и я нашел исправление. Этот тайм-аут вызван утечкой соединения. В моем случае я использую метод httpDelete и не потребляю ответ. Вместо этого проверьте статус ответа.

Исправление: объект ответа должен быть потреблен. Чтобы обеспечить надлежащее освобождение системных ресурсов, необходимо закрыть поток контента, связанный с объектом.

Итак, я использовал EntityUtils.consumeQuietly(response.getEntity());, который гарантирует, что контент объекта полностью потребляется, и поток контента, если он существует, закрыт.

Ответ 2

Я исправил это! добавьте mPost.releaseConnection() в finally.

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

DO обновить пакет org.apache.httpcomponents до 4.2.1

Ответ 3

Просто поместите строку, в которой вы получаете свой ответ, внутри try-with-resources и используйте CloseableHttpResponse вместо HttpResponse следующим образом:

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

Объект mHttpResponse будет автоматически использован и закрыт для вас.

Надеюсь это поможет!

Ответ 4

Это также может произойти, если вы используете ApacheHttpClient с DropWizard 0.6.2, который за кулисами создает MultiThreadedHttpConnectionManager с настройкой по умолчанию - и эта конфигурация по умолчанию допускает одновременное одновременное соединение HTTP подробнее здесь.

Таким образом, с этой конфигурацией, если ваш сервер становится загруженным и каждый раз запрашивает один и тот же хост, вы будете иметь максимальное количество подключений, которые будут выполняться одновременно!

Ответ 5

Как сказал Рама, это может быть признаком утечки соединения.

releaseConnection() может помочь решить эту проблему, но вам может потребоваться выяснить причину.

Кроме того, это может произойти из-за отсутствия доступного соединения, которое вы можете арендовать, что может произойти, если у вас нет конфигурации timeout для HttpClient. В этом случае releaseConnection() не поможет.

Ответ 6

На самом деле... Когда вы закончите с ответом, просто закройте его, не нужно закрывать соединение.

CloseableHttpResponse response = client.execute(httpPost, context);

... делать то, что нужно с этим делать...

response.close();

Ответ 7

Мы столкнулись с той же проблемой, и мы были ограничены, потому что исходное значение DefaultMaxPerRoute для соединения из пула равно 2. У нас был API, который запускал разные вызовы с одним и тем же URI, но с другим телом. Как только мы установим это явно на более высокое значение, как это

PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
    cm.setMaxTotal(40);
    cm.setDefaultMaxPerRoute(20);

мы смогли решить это.