HttpClient 4.0.1 - 如何释放连接?

Ric*_*d H 70 java connection apache-httpclient-4.x

我对一堆URL进行循环,对于每一个我正在执行以下操作的URL:

private String doQuery(String url) {

  HttpGet httpGet = new HttpGet(url);
  setDefaultHeaders(httpGet); // static method
  HttpResponse response = httpClient.execute(httpGet);   // httpClient instantiated in constructor

  int rc = response.getStatusLine().getStatusCode();

  if (rc != 200) {
    // some stuff...
    return;
  }

  HttpEntity entity = response.getEntity();

  if (entity == null) {
    // some stuff...
    return;
  }

  // process the entity, get input stream etc

}
Run Code Online (Sandbox Code Playgroud)

第一个查询没问题,第二个查询抛出此异常:

线程"main"中的异常java.lang.IllegalStateException:无效使用SingleClientConnManager:仍然分配了连接.确保在分配另一个连接之前释放连接.在org.apache.http.impl.conn.SingleClientConnManager.getConnection(SingleClientConnManager.java:199)org.apache.http.impl.conn.SingleClientConnManager $ 1.getConnection(SingleClientConnManager.java:173)......

这只是一个简单的单线程应用程序.我该如何发布此连接?

Yad*_*adu 95

Httpcomponents 4.1推荐的方法是关闭连接并释放任何底层资源:

EntityUtils.consume(HttpEntity)
Run Code Online (Sandbox Code Playgroud)

其中HttpEntity通过是一个响应实体.

  • EntityUtils类中没有使用消耗方法http://developer.android.com/reference/org/apache/http/util/EntityUtils.html (4认同)

Sni*_*las 32

这似乎很有效:

      if( response.getEntity() != null ) {
         response.getEntity().consumeContent();
      }//if
Run Code Online (Sandbox Code Playgroud)

即使您没有打开其内容,也不要忘记使用该实体.例如,您希望响应中的HTTP_OK状态并且没有得到它,您仍然必须使用该实体!

  • consumeContent()现在(4.1.2)已弃用.换句话说:EntityUtils.consume(response.getEntity()); (11认同)
  • 对于那些想知道的人来说,后续操作:如果您不使用该实体,则 HttpClient 会认为该请求仍在进行中。一旦堆积了足够多的未消耗的请求,后续请求将无限期地阻塞。 (2认同)

Ric*_*d H 23

要回答我自己的问题:要释放连接(以及与请求关联的任何其他资源),您必须关闭HttpEntity返回的InputStream:

InputStream is = entity.getContent();

.... process the input stream ....

is.close();       // releases all resources
Run Code Online (Sandbox Code Playgroud)

来自文档

  • 我不这么认为,我这样做,我得到"无效使用SingleClientConnManager:连接仍然分配".它可以通过ClientConnectionManager完成,我可以从httpClient获得,但它似乎不对 (3认同)
  • 我可以确认通过关闭InputStream我看到调试消息:org.apache.http.impl.conn.BasicClientConnectionManager(18314):释放连接 (2认同)

wik*_*ier 19

从版本4.2开始,他们引入了一种更方便的方法来简化连接释放:HttpRequestBase.releaseConnection()


Chr*_*ris 12

我正在讨论专门针对Apache HttpClient 4.0.1的详细解决方案.我正在使用这个HttpClient版本,因为它是由WAS v8.0提供的,我需要在Apache Wink v1.1.1中使用提供的HttpClient,也是由WAS v8.0提供的,对Sharepoint进行一些NTLM认证的REST调用.

在Apache HttpClient邮件列表上引用Oleg Kalnichevski:

几乎所有这些代码都不是必需的.(1)只要实体内容被消耗到流的末尾,HttpClient就会自动释放底层连接; (2)HttpClient将在读取响应内容时自动释放引发的任何I/O异常的底层连接.在这种情况下不需要特殊处理.

事实上,这足以确保正确释放资源:

HttpResponse rsp = httpclient.execute(target, req); 
HttpEntity entity = rsp.getEntity(); 
if (entity != null) {
     InputStream instream = entity.getContent();
     try {
         // process content
     } finally {
         instream.close();
         // entity.consumeContent() would also do
     } 
}
Run Code Online (Sandbox Code Playgroud)

这就对了.

资源


Jig*_*hel 7

如果不消耗响应,则可以使用以下代码中止请求:

// Low level resources should be released before initiating a new request
HttpEntity entity = response.getEntity();

if (entity != null) {
    // Do not need the rest
    httpPost.abort();
}
Run Code Online (Sandbox Code Playgroud)

参考:http://hc.apache.org/httpcomponents-client-ga/tutorial/html/fundamentals.html#d5e143

Apache HttpClient版本:4.1.3