it-swarm.com.de

httpclient-Ausnahme "org.Apache.http.conn.ConnectionPoolTimeoutException: Wartezeit für Verbindung"

Ich versuche, eine Anfrage mit folgendem Code an meinen Server zu senden. es scheiterte immer bei der 3. Anfrage.

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();
    }
}

die Ausnahme wie folgt:

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)
28
user1447011

Ich hatte das gleiche Problem und fand den Fix ... Diese Zeitüberschreitung ist auf ein Verbindungsleck zurückzuführen. In meinem Fall verwende ich die httpDelete-Methode und verbrauchte die Antwort nicht. Überprüfen Sie stattdessen den Status der Antwort. 

Der Fix ist, dass die Antworteinheit verbraucht werden muss. Um eine ordnungsgemäße Freigabe der Systemressourcen sicherzustellen, muss der mit der Entität verknüpfte Inhaltsstrom geschlossen werden.

Also habe ich EntityUtils.consumeQuietly(response.getEntity()); verwendet, um sicherzustellen, dass der Entity-Inhalt vollständig verbraucht wird und der Content-Stream, falls vorhanden, geschlossen wird.

Ich habe es repariert! Fügen Sie mPost.releaseConnection() in finally-Blöcken hinzu.

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

Aktualisieren Sie das Paket org.Apache.httpcomponents auf 4.2.1

25
user1447011

Schreiben Sie einfach die Zeile, in der Sie Ihre Antwort erhalten, in try-with-resources und verwenden Sie CloseableHttpResponse statt HttpResponse wie folgt:

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

Das mHttpResponse-Objekt wird automatisch verbraucht und für Sie geschlossen

Hoffe das hilft!

2
Suyog Tilak

Dies kann auch passieren, wenn Sie ApacheHttpClient mit DropWizard 0.6.2 verwenden, wodurch hinter den Kulissen eine MultiThreadedHttpConnectionManager mit einer Standardkonfiguration erstellt wird. Diese Standardkonfiguration erlaubte nur zwei gleichzeitige HTTP-Verbindungen gleichzeitig. Weitere Informationen hier .

Wenn bei dieser Konfiguration der Server ständig überlastet wird und ständig Anfragen an denselben Host stellt, haben Sie maximal 2 Verbindungen, die gleichzeitig ausgeführt werden dürfen!

2
Brad Parks

Eigentlich ... Wenn Sie mit der Antwort fertig sind, schließen Sie sie einfach, ohne die Verbindung zu schließen.

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

... mach was du damit machen musst ...

response.close();
0
Johan Andersson

Wie Rama sagte, könnte dies ein Zeichen für ein Verbindungsleck sein. 

releaseConnection() könnte helfen, dieses Problem zu beheben, aber Sie müssen möglicherweise die Ursache ermitteln.

Dies kann auch passieren, weil es keine verfügbare Verbindung gibt, die Sie leasen können. Dies kann passieren, wenn Sie timeout config für die HttpClient nicht haben. In diesem Fall würde releaseConnection() nicht helfen.

0
Sanghyun Lee