`

HttpClient容易忽视的细节——连接关闭

    博客分类:
  • java
阅读更多
HttpClient client = new HttpClient();
HttpMethod method = new GetMethod("http://www.apache.org");
try {
  client.executeMethod(method);
  byte[] responseBody = null;
  
  responseBody = method.getResponseBody();
  
} catch (HttpException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
} catch (IOException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
}finally{
  method.releaseConnection();
  
}

大部分人使用HttpClient都是使用类似上面的事例代码,包括Apache官方的例子也是如此。最近我在使用HttpClient是发现一次循环发送大量请求到服务器会导致APACHE服务器的链接被占满,后续的请求便排队等待。
我服务器端APACHE的配置
Timeout 30
KeepAlive On   #表示服务器端不会主动关闭链接
MaxKeepAliveRequests 100
KeepAliveTimeout 180 

因此这样的配置就会导致每个链接至少要过180S才会被释放,这样在大量请求访问时就必然会造成链接被占满,请求等待的情况。
在通过DEBUH后发现HttpClient在method.releaseConnection()后并没有把链接关闭,这个方法只是将链接返回给connection manager。如果使用HttpClient client = new HttpClient()实例化一个HttpClient connection manager默认实现是使用SimpleHttpConnectionManager。SimpleHttpConnectionManager有个构造函数如下
/**
 * The connection manager created with this constructor will try to keep the 
 * connection open (alive) between consecutive requests if the alwaysClose 
 * parameter is set to <tt>false</tt>. Otherwise the connection manager will 
 * always close connections upon release.
 * 
 * @param alwaysClose if set <tt>true</tt>, the connection manager will always
 *    close connections upon release.
 */
public SimpleHttpConnectionManager(boolean alwaysClose) {
    super();
    this.alwaysClose = alwaysClose;
}

看方法注释我们就可以看到如果alwaysClose设为true在链接释放之后connection manager 就会关闭链。在我们HttpClient client = new HttpClient()这样实例化一个client时connection manager是这样被实例化的
this.httpConnectionManager = new SimpleHttpConnectionManager();

因此alwaysClose默认是false,connection是不会被主动关闭的,因此我们就有了一个客户端关闭链接的方法。
方法一:
把事例代码中的第一行实例化代码改为如下即可,在method.releaseConnection();之后connection manager会关闭connection 。
HttpClient client = new HttpClient(new HttpClientParams(),new SimpleHttpConnectionManager(true) );

方法二:
实例化代码使用:HttpClient client = new HttpClient();
在method.releaseConnection();之后加上
((SimpleHttpConnectionManager)client.getHttpConnectionManager()).shutdown();

shutdown源代码很简单,看了一目了然
public void shutdown() {
    httpConnection.close();
}

方法三:
实例化代码使用:HttpClient client = new HttpClient();
在method.releaseConnection();之后加上
client.getHttpConnectionManager().closeIdleConnections(0);此方法源码代码如下:
public void closeIdleConnections(long idleTimeout) {
    long maxIdleTime = System.currentTimeMillis() - idleTimeout;
    if (idleStartTime <= maxIdleTime) {
        httpConnection.close();
    }
}

将idleTimeout设为0可以确保链接被关闭。
以上这三种方法都是有客户端主动关闭TCP链接的方法。下面再介绍由服务器端自动关闭链接的方法。
方法四:
代码实现很简单,所有代码就和最上面的事例代码一样。只需要在HttpMethod method = new GetMethod("http://www.apache.org");加上一行HTTP头的设置即可
method.setRequestHeader("Connection", "close");

看一下HTTP协议中关于这个属性的定义:
HTTP/1.1 defines the "close" connection option for the sender to signal that the connection will be closed after completion of the response. For example,
       Connection: close
现在再说一下客户端关闭链接和服务器端关闭链接的区别。如果采用客户端关闭链接的方法,在客户端的机器上使用netstat –an命令会看到很多TIME_WAIT的TCP链接。如果服务器端主动关闭链接这中情况就出现在服务器端。
参考WIKI上的说明http://wiki.apache.org/HttpComponents/FrequentlyAskedConnectionManagementQuestions
The TIME_WAIT state is a protection mechanism in TCP. The side that closes a socket connection orderly will keep the connection in state TIME_WAIT for some time, typically between 1 and 4 minutes.
TIME_WAIT的状态会出现在主动关闭链接的这一端。TCP协议中TIME_WAIT状态主要是为了保证数据的完整传输。具体可以参考此文档:
http://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/unix-socket-faq-2.html#ss2.7
另外强调一下使用上面这些方法关闭链接是在我们的应用中明确知道不需要重用链接时可以主动关闭链接来释放资源。如果你的应用是需要重用链接的话就没必要这么做,使用原有的链接还可以提供性能。
分享到:
评论
9 楼 可爱的小狗 2016-04-27  
学习了  
8 楼 javatar 2008-11-23  
官方文档有建议使用空闲连接检查线程:
import org.apache.commons.httpclient.util.IdleConnectionTimeoutThread;
// 创建线程
IdleConnectionTimeoutThread thread = new IdleConnectionTimeoutThread();
// 注册连接管理器
thread.addConnectionManager(httpClient.getHttpConnectionManager());
// 启动线程
thread.start();
// 在最后,关闭线程
thread.shutdown();
7 楼 sdh5724 2008-10-29  
楼上的说法是对的, 但是, 性能来说, 是不合适的.
首先, 我想问你, 既然是轮询, 为什么HttpURLConnection要每次创建.  既然是个持续的过程, 就不应该每次HttpURLConnection对象重新创建, 你应该重复使用这个对象. HttpURLConnection会持有连接的, 如果断开, 我记得他会去尝试连接.
6 楼 SeanHe 2008-10-28  
kjah 写道
但使用netstat发现很多TIME_WAIT,时间长点后会出现端口都被占用的状况 address already in use :connect,使用HttpURLConnection.disconnect()也没有效果。

如果你是应为客户端出现很多的TIME_WAIT造成端口占用,你不妨试一下“方法四”在HTTP请求头上设置"Connection", "close"这样服务器会来主动关闭链接,这样就不会在客户端产生很多的TIME_WAIT
5 楼 kjah 2008-10-28  
我是google到这里的。。。
您对HttpClient 的关闭分析的很透彻
请教HttpURLConnection和URLConnection怎么关闭链接?
我需要轮询一个网址,但使用netstat发现很多TIME_WAIT,时间长点后会出现端口都被占用的状况 address already in use :connect,使用HttpURLConnection.disconnect()也没有效果。
4 楼 fly_ever 2008-09-11  
引用

另外强调一下使用上面这些方法关闭链接是在我们的应用中明确知道不需要重用链接时可以主动关闭链接来释放资源。如果你的应用是需要重用链接的话就没必要这么做,使用原有的链接还可以提供性能。

正如你所说,实际上是只有并发量很高的时候才会发生链接占满的情况。
而如果没有这么高的并发量,我们没必要去实现代码来关闭连接。
因为我们在代码中实现主动关闭的功能的同时,也丧失了性能上的优势。
因此,我觉得遇到这种情况,应该把设置中的keepAliveTimeout调低,显得更好一些。
   1. Timeout 30  
   2. KeepAlive On   #表示服务器端不会主动关闭链接  
   3. MaxKeepAliveRequests 100  
   4. KeepAliveTimeout 180   

不过,这里提供的HttpClient关闭的详细信息,还是很有价值的。
3 楼 jorsef 2008-09-10  
受用,非常感谢
2 楼 SeanHe 2008-09-06  
HttpClient client = new HttpClient(); 如果这样进行实例化,默认使用SimpleHttpConnectionManager作为connection manager,SimpleHttpConnectionManager没有连接池,只管理一个连接
1 楼 JavaTestJava 2008-09-05  
方法二:
实例化代码使用:HttpClient client = new HttpClient();
在method.releaseConnection();之后加上
Java代码
((SimpleHttpConnectionManager)client.getHttpConnectionManager()).shutdown(); 

((SimpleHttpConnectionManager)client.getHttpConnectionManager()).shutdown();
shutdown源代码很简单,看了一目了然
Java代码
public void shutdown() {  
    httpConnection.close();  


public void shutdown() {
    httpConnection.close();
}

方法二中的httpConnection.close();这里没有参数么?
httpConnection为默认全局的那个连接?

相关推荐

    httpclient jar包——相关jar

    httpclient jar包——相关jar,用于http相关开发! httpclient jar包——相关jar,用于http相关开发! httpclient jar包——相关jar,用于http相关开发!

    httpClient实例httpClient调用 http/https实例 忽略SSL验证

    在IT行业中,HttpClient是一个常用的Java库,用于执行HTTP和HTTPS请求。这个实例主要涉及如何配置HttpClient来忽略SSL(Secure Socket Layer)...但请记住,忽视SSL验证在生产环境中可能会导致安全隐患,务必谨慎对待。

    HTTPClient工具类,完整

    HTTPClient工具类,完整,HTTPClient工具类,完整,HTTPClient工具类,完整HTTPClient工具类,完整,HTTPClient工具类,完整

    HttpAsyncClient 异步httpClient和同步httpClient连接池的工具类 包含jar

    HttpAsyncClient连接池的使用,项目中频繁发送http请求,同步http阻塞主线程,影响性能,使用 HttpAsyncClient可使性能提高,这里配合连接池使用,效果更好,同时还附带同步httpClient的连接池使用

    http请求工具类HttpClientUtil,get,post请求(csdn)————程序.pdf

    在 HttpClientUtil 中,`EntityUtils` 被用来读取和关闭响应实体。`EntityUtils.toString` 用于将 HttpEntity 转换为字符串,便于进一步解析或操作。 6. **使用示例**: 用户可以调用 `doGetJson` 或 `doPostJson`...

    httpclient4.4

    《HttpClient 4.4详解——构建高效可靠的网络通信》 HttpClient是Apache软件基金会下的一个开源项目,主要提供了Java语言环境下的HTTP客户端编程接口。HttpClient 4.4版本是该库的一个重要里程碑,它在功能、性能和...

    关闭HttpClient日志的logback文件

    关闭HttpClient日志的logback文件

    httpclient.jar包下载

    1. **连接管理**:HttpClient通过HttpConnectionManager接口控制HTTP连接的创建、复用和关闭,有效地管理连接池,避免了频繁建立新连接带来的性能开销。 2. **请求和响应模型**:HttpClient使用HttpRequest和...

    httpclient jar

    二、HttpClient核心类——HttpClient `HttpClient`是HttpClient库的核心组件,它是HTTP请求的发起者,负责管理连接、配置策略和执行请求。通过`HttpClient`实例,开发者可以创建并发送HTTP请求,同时接收和解析HTTP...

    httpclient

    5. **关闭资源**:执行完请求后,关闭HttpClient和相关连接,释放系统资源。 **四、示例代码** ```java CloseableHttpClient httpClient = HttpClients.createDefault(); HttpGet httpGet = new HttpGet(...

    使用httpClient访问https+443端口号。

    8. **关闭连接**:记得在完成请求后关闭HttpClient和响应实体,以释放资源。 9. **错误处理**:处理可能出现的异常,如网络问题、认证失败或证书问题。 通过这些步骤,我们可以使用Apache HttpClient库安全地与443...

    httpclient4.5.5所有包

    - **连接管理**:HttpClient 提供了连接池管理器,可以复用已建立的连接,减少网络延迟,提高效率。 - **HTTP 方法**:支持 GET、POST、PUT、DELETE 等多种 HTTP 方法,以及 HEAD、OPTIONS、TRACE 等其他标准方法...

    Httpclient依赖包

    2. **资源管理**:由于HttpClient涉及到网络连接和线程,因此需要正确管理和关闭资源,避免内存泄漏和连接泄露。 3. **异常处理**:HttpClient抛出的异常通常包含了丰富的错误信息,通过捕获和处理这些异常,可以更...

    httpClient需要的jar包

    10. **性能优化**:通过配置连接超时、响应超时、线程池大小等参数,以及使用合适的连接管理策略,可以进一步优化HttpClient的性能。 在实际使用HttpClient时,需要根据项目需求选择合适的版本,理解其工作原理,...

    httpclient httpclient.jar

    通常,我们创建一个HttpClient实例,并设置其配置参数,如连接超时、重试策略等。 2. **HttpHost**:表示目标HTTP服务器的信息,包括主机名、端口和协议(HTTP或HTTPS)。 3. **HttpGet/HttpPost**:这些是执行...

    HTTPClient 的一个封装

    6. **关闭资源**:确保在完成请求后关闭连接,避免资源泄露。 在封装过程中,可能会有以下高级特性的实现: - **连接池管理**:通过`PoolingHttpClientConnectionManager`管理连接,提高性能和并发能力。 - **异步...

    HttpClient

    - **连接管理器**:管理器允许对连接池进行高级控制,如连接池的创建和关闭、连接的借出和回收、连接回收策略等。 - **代理配置**:在某些情况下,HTTP请求可能需要通过代理服务器,HttpClient提供了灵活的代理配置...

    commons-httpclient.rar

    6. **释放资源**:完成操作后,记得关闭连接,释放资源。 Apache Commons HttpClient是一个功能强大且高度可定制的HTTP客户端库,对于Java开发者来说,它是进行HTTP通信的重要工具。其丰富的功能和灵活性使其成为...

    httpclient4.3工具类

    这些方法通常会隐藏复杂的HttpClient配置细节,使代码更加简洁易读。 总结起来,`httpclient4.3工具类`是一个针对HttpClient 4.3的自定义包装,它封装了常见的HTTP操作,提供了便捷的接口供项目中使用。理解这个...

Global site tag (gtag.js) - Google Analytics