httpclientexception“org.apache.http.conn.ConnectionPoolTimeoutException:超时等待连接”

我正在尝试使用以下代码向我的服务器发送请求。 总是在第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.(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

如果您使用ApacheHttpClient和DropWizard 0.6.2,后台创建一个具有默认配置的MultiThreadedHttpConnectionManager ,这种情况也会发生 – 而且默认配置一次只允许2个并发的http连接。

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

只需将您获得响应的行放在try-with-resources中,并使用CloseableHttpResponse而不是HttpResponse,如下所示:

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

mHttpResponse对象将自动使用并为您关闭

希望这可以帮助!