簡體   English   中英

httpclient 異常“org.apache.http.conn.ConnectionPoolTimeoutException:等待連接超時”

[英]httpclient exception “org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection”

我正在嘗試使用以下代碼向我的服務器發送請求。 它總是在第三次請求時失敗。

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)

我遇到了同樣的問題,我找到了解決方法。 此超時是因為連接泄漏。 就我而言,我使用的是httpDelete方法並且不消耗響應。 相反,我正在檢查響應的狀態。

解決方法是,需要使用響應實體。 為了保證系統資源的正確釋放,必須關閉與實體關聯的內容流。

所以我使用了EntityUtils.consumeQuietly(response.getEntity()); 這確保實體內容被完全消耗,並且內容流(如果存在)被關閉。

我已經修好了! finally塊中添加mPost.releaseConnection()

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

更新包org.apache.httpcomponents到 4.2.1

只需將在 try-with-resources 中獲取響應的行放在 try-with-resources 中,然后使用 CloseableHttpResponse 而不是 HttpResponse ,如下所示:

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

mHttpResponse 對象將自動為您使用和關閉

希望這可以幫助!

使用CloseableHttpClient而不是HttpClient 您將獲得CloseableHttpResponse而不是支持close()HttpResponse 因此,當您完成響應時,只需關閉它即可,無需關閉連接。

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

...做你需要做的事情:

response.close();

如果您將ApacheHttpClient與 DropWizard 0.6.2 一起使用,也會發生這種情況,它在后台創建了一個帶有默認配置的MultiThreadedHttpConnectionManager - 該默認配置一次只允許 2 個並發 http 連接, 更多信息請點擊此處

因此,使用此配置,如果您的服務器被淹沒並一直向同一主機發出請求,則一次最多允許運行 2 個連接!

我們遇到了同樣的問題,我們受到限制,因為來自池的連接的 DefaultMaxPerRoute 的初始值為 2。我們是一個 API,它會使用相同的 URI 觸發不同的調用,但主體不同。 一旦我們像這樣明確地將它設置為更高的值

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

我們能夠解決它。

我們在通過 spark 寫入和讀取鑲木地板時遇到了這個錯誤。 確切的錯誤是:
com.amazonaws.SdkClientException:無法執行 HTTP 請求:等待池中的連接超時

終於搞清楚這和Hadoop升級到3.1.3版本有關

似乎在這個新版本的 Hadoop 中,屬性名稱從:
fs.s3a.connection.maximum
到:
spark.hadoop.fs.s3a.connection.maximum

在我們的 spark 配置中重命名屬性,讓我們回到正軌。

我遇到了同樣的錯誤。 事實證明,我需要關閉響應。

CloseableHttpResponse response = null;
try {
       response = ##some code
} catch(Exception e) {
  if (response != null) {
      response.close();
  }
}

正如Rama所說,這可能是連接泄漏的跡象。

releaseConnection()可以幫助解決此問題,但您可能需要找出根本原因。

此外,這可能是因為沒有您可以租用的可用連接,當您沒有HttpClient timeout配置時可能會發生這種情況。 在這種情況下, releaseConnection()無濟於事。

在我的情況下,使用實體內容流的 bufferedReader 沒有被關閉。 關閉它解決了錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM