httpclient异常“org.apache.http.conn.ConnectionPoolTimeoutException:等待连接超时”
Posted
技术标签:
【中文标题】httpclient异常“org.apache.http.conn.ConnectionPoolTimeoutException:等待连接超时”【英文标题】:httpclient exception "org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection" 【发布时间】:2012-08-09 00:08:34 【问题描述】:我正在尝试使用以下代码向我的服务器发送请求。它总是在第三次请求时失败。
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)
【问题讨论】:
【参考方案1】:我遇到了同样的问题,我找到了解决方法。
此超时是由于连接泄漏。就我而言,我使用的是httpDelete
方法并且不消耗响应。相反,我正在检查响应的状态。
解决方法是,需要消耗响应实体。为了确保系统资源的正确释放,必须关闭与实体关联的内容流。
所以我使用了EntityUtils.consumeQuietly(response.getEntity());
,它确保实体内容被完全消费,并且内容流(如果存在)被关闭。
【讨论】:
在忽略响应时,与 Fluent HTTP 客户端有类似的问题。仍然必须调用 execute().discardContent() 以避免连接泄漏。 太烦人了......如果你不使用它,图书馆应该丢弃它......或者至少给你一个警告......response.close()
呢?
如果出现异常并且在这种情况下响应对象将为空怎么办?这种场景我们如何释放连接?【参考方案2】:
我已经解决了!在finally
块中添加mPost.releaseConnection()
。
try
catch (Exception e)
finally
mPost.releaseConnection();
请务必将软件包 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 对象将被自动使用并为您关闭
希望这会有所帮助!
【讨论】:
客户端变量必须是 CloseableHttpClient 的实例才能工作【参考方案4】:使用CloseableHttpClient
代替HttpClient
。你会得到一个CloseableHttpResponse
而不是支持close()
的HttpResponse
。因此,当您完成响应后,只需关闭它,无需关闭连接。
CloseableHttpResponse response = closableHttpClient.execute(httpPost, context);
...做你需要做的事情:
response.close();
【讨论】:
虽然这可能是正确的,但似乎它可能是对一个或多个其他答案的评论,而不是本身的答案,因为它并没有真正直接解决问题。我建议要么编辑它以将其表述为问题的答案,使其成为对不同答案的评论,要么创建您自己的自我回答问题,并在此处的评论中链接到该问题。【参考方案5】:如果您将 ApacheHttpClient
与 DropWizard 0.6.2 一起使用,也会发生这种情况,这会在后台创建具有默认配置的 MultiThreadedHttpConnectionManager
- 并且该默认配置一次只允许 2 个并发 http 连接 @987654321 @。
因此,使用此配置,如果您的服务器被淹没并且一直向同一主机发出请求,那么您一次最多允许运行 2 个连接!
【讨论】:
【参考方案6】:我们遇到了同样的问题,但我们受到了限制,因为来自池的连接的 DefaultMaxPerRoute 初始值为 2。我们的 API 会使用相同的 URI 触发不同的调用,但主体不同。一旦我们像这样明确地将其设置为更高的值
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(40);
cm.setDefaultMaxPerRoute(20);
我们能够解决它。
【讨论】:
【参考方案7】:我们在通过 spark 写入和读取镶木地板时遇到了这个错误。 确切的错误是: com.amazonaws.SdkClientException:无法执行 HTTP 请求:等待来自池的连接超时
我们终于发现这与 Hadoop 升级到 3.1.3 版本有关 似乎在这个新版本的 Hadoop 中,属性名称已更改为:fs.s3a.connection.maximum 到:spark.hadoop.fs.s3a.connection.maximum 在我们的 spark 配置中重命名属性,让我们回到正轨。
【讨论】:
【参考方案8】:我遇到了同样的错误。原来我需要关闭响应。
CloseableHttpResponse response = null;
try
response = ##some code
catch(Exception e)
if (response != null)
response.close();
【讨论】:
我想这里最好用try with resource。【参考方案9】:正如Rama 所说,这可能是连接泄漏的迹象。
releaseConnection()
可以帮助解决此问题,但您可能需要找出根本原因。
另外,这可能是因为没有可用的连接可以租用,当您没有 HttpClient
的 timeout
配置时可能会发生这种情况。在这种情况下,releaseConnection()
将无济于事。
【讨论】:
如果出现异常并且在这种情况下响应对象将为空怎么办?如果我不使用资源尝试,我们如何释放连接?【参考方案10】:在我的例子中,使用实体内容流的 bufferedReader 没有被关闭。关闭它解决了错误。
【讨论】:
以上是关于httpclient异常“org.apache.http.conn.ConnectionPoolTimeoutException:等待连接超时”的主要内容,如果未能解决你的问题,请参考以下文章
解决httpclient抛出URISyntaxException异常
HttpClient.PostAsync 崩溃应用。如何捕捉异常?