有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java 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)

共 (6) 个答案

  1. # 1 楼答案

    我已经修好了!在finally块中添加mPost.releaseConnection()

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

    请将包org.apache.httpcomponents更新为4.2.1

  2. # 2 楼答案

    使用CloseableHttpClient代替HttpClient。您将得到一个CloseableHttpResponse而不是一个支持close()HttpResponse。因此,当您完成响应时,只需关闭它,无需关闭连接

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

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

    response.close();
    
  3. # 3 楼答案

    如果将ApacheHttpClient与DropWizard 0.6.2一起使用,也会发生这种情况。DropWizard 0.6.2在幕后创建了一个带有默认配置的MultiThreadedHttpConnectionManager,并且默认配置一次只允许2个并发http连接more info here

    因此,使用此配置,如果您的服务器被淹没,并且一直向同一主机发出请求,那么一次最多允许运行2个连接

  4. # 4 楼答案

    只需将获得响应的行放在内部,使用资源进行尝试,并使用CloseableHttpResponse而不是HttpResponse,如下所示:

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

    MHTTPRESSONSE对象将自动消费并为您关闭

    希望这有帮助

  5. # 5 楼答案

    我也有同样的问题,我找到了解决办法。 此超时是由于连接泄漏造成的。在我的例子中,我使用的是httpDelete方法,而不是使用响应。相反,我正在检查响应的状态

    修复方法是,需要使用响应实体。为了确保系统资源的正确释放,必须关闭与实体关联的内容流

    因此,我使用了EntityUtils.consumeQuietly(response.getEntity());,它确保实体内容被完全使用,并且内容流(如果存在)被关闭

  6. # 6 楼答案

    我们面临同样的问题,我们受到了限制,因为来自池的连接的初始值DefaultMaxPerRoute为2。我们的API将使用相同的URI但不同的主体触发不同的调用。一旦我们明确地将其设置为更高的值,就像这样

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

    我们能够解决它