httpclient链接关闭问题(转帖)

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Java中,使用HttpClient库连接SSH协议服务器并不直接支持。HttpClient主要用于HTTP和HTTPS请求,而SSH协议是一种用于安全登录远程服务器的协议,与HTTP无关。 要在Java中使用SSH协议连接服务器,可以使用JSch库。JSch是一个纯Java实现的SSH2协议库,可用于在Java程序中执行SSH操作。 首先,需要在项目中引入JSch的依赖,例如使用Maven的话,在pom.xml文件中添加如下配置: ```xml <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.55</version> </dependency> ``` 然后,可以使用以下样例代码创建一个SSH连接,执行一些命令: ```java import com.jcraft.jsch.JSch; import com.jcraft.jsch.Session; public class SSHConnectionExample { public static void main(String[] args) { try { JSch jsch = new JSch(); Session session = jsch.getSession("username", "hostname", 22); session.setPassword("password"); session.setConfig("StrictHostKeyChecking", "no"); session.connect(); // 在SSH连接上执行一些命令 // ... session.disconnect(); } catch (Exception e) { e.printStackTrace(); } } } ``` 以上代码中,"username"是SSH服务器的用户名,"hostname"是SSH服务器的主机名或IP地址,22是SSH服务器默认的端口号,"password"是相应的登录密码。 在session连接成功后,可以通过执行一些命令来与远程服务器进行交互。例如,可以使用session的openChannel方法打开一个Channel并执行命令、读取输出结果、发送指令等。 需要注意的是,连接SSH服务器需要正确的用户名和密码,以及正确配置的SSH服务器。如果有需要,还可以使用密钥文件进行身份验证。 希望以上信息能够帮助到您。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值