使用PoolingHttpClientConnectionManager时需要释放连接

3
根据定义,PoolingHttpClientConnectionManager 可以重用连接。那么,
1)在使用后是否需要显式释放连接?
2)如果连接被释放,管理器将无法重用该连接?
executing a method?

CloseableHttpClient closableHttpClient = HttpClients.custom().setConnectionManager(getPoolingHttpClientConnectionManager()).build();
        HttpPost post = new HttpPost(resourcePath);                    
                try {
                    return closableHttpClient.execute(post);

                } catch (IOException e) {
                   //handle exception
                }finally {
                    post.releaseConnection();
                }

2
关闭CloseableHttpResponse最终会关闭连接。根据您之前的帖子,您可能正在尝试以多线程方式执行池化。请参见Threaded Request Execution example,其他示例在此处找到。还可以在第2.4节中找到更多解释。 - Paul Samsotha
2个回答

5

典型应用场景是:

CloseableHttpClient closableHttpClient = HttpClients.custom().setConnectionManager(getPoolingHttpClientConnectionManager()).build();
HttpGet httpget = new HttpGet("http://localhost/");
CloseableHttpResponse response = httpclient.execute(httpget);
try {
    HttpEntity entity = response.getEntity();
    if (entity != null) {
        InputStream instream = entity.getContent();
        try {
            // do something useful
        } finally {
            instream.close();
        }
    }
} finally {
    response.close();
}
  1. instream.close()response.close()会显式释放底层连接。这里所谓的“释放”并不是直接关闭套接字,而是要检查以下几个条件: 1)流是否全部消耗完毕 2)连接是否设置为可重用 3)服务器是否响应保持连接

  2. closableHttpClient.close()将关闭连接池。


关于 CloseableHttpClient.close() 会关闭 连接池 的提示不错。我使用了 "try with resource" 语句,发现我的连接池在此之后处于关闭状态。对我来说,关闭 客户端 会导致 管理器 关闭似乎有些奇怪。不过,感谢您验证我不关闭客户端也不会出现内存泄漏问题。 - Fearnbuster

1
(1) 连接管理器无法知道应用层是否已经完成对租赁连接的读取,因此必须明确将其释放回管理器。
(2) 是否可以重复使用连接取决于多个因素:响应消息必须完全被消耗、客户端和服务器必须表明保持连接的意图、没有I/O错误等。

3
https://hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/examples/client/ClientConnectionRelease.java中提到,连接在关闭输入流后立即释放回池中。一些人评论说它会在response.close()时释放,并且许多示例支持此操作。但是HttpResponseProxy.close()的javadoc说明“释放连接而不保持活动状态的选项。这是一个硬关机,意味着连接被关闭。使用releaseConnection()进行优雅的释放。” 有没有值得参考的参考资料来确认哪个是正确的? - Sumit Jain
两个语句都是正确的。如果在调用CloseableHttpResponse#close之前完全消耗响应实体,则底层连接将以一致且可重复使用的状态返回到连接管理器中。随后对#close的调用没有任何效果。 - ok2c
好的,但是HttpResponseProxy.close()代码会调用this.connHolder.abortConnection(),如果(this.connHolder != null),这个检查是否确保在调用close之前,connHolder已经被完全消耗,从而变为null?另外,您能否指出触发器在哪个类中在输入流关闭时触发? - Sumit Jain
http://hc.apache.org/httpcomponents-client-4.5.x/httpclient/xref/org/apache/http/conn/EofSensorInputStream.html - ok2c
谢谢,这解决了一些问题,但它如何与HttpResponseProxy.close和this.connHolder != null联系起来? - Sumit Jain
只是为了澄清您的问题:ConnectionHolder#releaseConnection 首先检查它是否已经被释放。当检测到 eof 或 close 时,ResponseEntityProxy 类会执行此操作。 请参见:https://github.com/apache/httpcomponents-client/blob/4.5.x/httpclient/src/main/java/org/apache/http/impl/execchain/ConnectionHolder.java#L95 和 https://github.com/apache/httpcomponents-client/blob/4.5.x/httpclient/src/main/java/org/apache/http/impl/execchain/ResponseEntityProxy.java#L115 - ChrisY

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接