apache common-httpclient的连接关闭问题

apache common-httpclient的连接关闭问题

| date : 2017.3.7 |

apache 提供的common-httpclient (3.1 的版本),在调用httpclient的时候,是很方便的,在实际的项目中,调用第三方服务,也经常使用;这次在客户现场发现了一个问题;

我们调用第三方的服务,第三方服务在监控连接的时候,提到我们发起的连接有许多的close_wait连接;

检查

原来是怀疑连接没有释放;检查了代码,是有调用了 releaseConnection的方法;没细看,看这个方法名,就是关闭连接了;有点怪异;

继续查下去;做了一个测试;目前使用httpclient的方法大致如下:

    private void doHttpTest(){
        HttpClient httpClient = new HttpClient();
        GetMethod get = new GetMethod("http://www.baidu.com");
        try{
            httpClient.executeMethod(get);
        } catch (Exception err){

        } finally {
            get.releaseConnection();
        }
    }

    @Test
    public void do100Test(){
        for(int i=0 ;i<100;i++){
            this.doHttpTest();
        }
        System.out.print("111");
    }

该方法在自测时候,在最后一个 System.out.print 方法打了断点;(知道为啥要留这个方法了吧,打断点用的。。哈哈哈) debug , 之后,检查了该进程发起的连接; 先看看 www.baidu.com的IP 吧;

百度的IP

JPS看看,咱的进程ID

来吧,检查一下进程 windons 下面的命令:netstat -ano|find "20168" |find "61." 计数命令:netstat -ano|find "20168" |find "61." /c

输入图片说明

输入图片说明

100个连接哦,,还都是 CLOSE_WAIT的; 好吧;就说明我们上面脚本中循环了100个,就压根没有是否端口呀。。。

抽丝剥茧啊

为啥,,这个是为啥。已经调用了 releaseConnection() ;难道是releaseConnection()的问题,要不看看的呗。 GetMethod --> HttpMethodBase --> HttpConnection --> HttpConnectionManager 好吧,这里是个接口。咋整,从 HttpClient入口,发现默认是使用 SimpleHttpConnectionManager ,走起; 源码如下: Alt text 看到了,坑的地方来了; if(this.alwaysClose) 这个值,默认是false的哦。。而且,貌似还没地方赋值的呢。。换句话说,默认是 finishLastResponse,查看这个方法,卧槽,厉害了,只是清理了 inputStream 呢。但连接木有关闭啊; 要关闭连接怎么办?我们自己来关闭?往下翻了翻,额,有个closeIdleConnections 的方法;这个的源码看了一下,额,关闭在Nms之前的连接呢。。恩。这个可以用; 试试看;

新的测试代码

新的测试代码如下:就补充了closeIdleConnections的内容;

   private void doHttpTest(){
        HttpClient httpClient = new HttpClient();
        GetMethod get = new GetMethod("http://www.baidu.com");
        try{
            httpClient.executeMethod(get);
        } catch (Exception err){
        } finally {
            get.releaseConnection();
            //就加了这里哈。。
            httpClient.getHttpConnectionManager().closeIdleConnections(0L);
        }
    }

    @Test
    public void do100Test(){
        for(int i=0 ;i<100;i++){
            this.doHttpTest();
        }
        System.out.print("111");
    }

同以上的测试过程,检查连接数: 输入图片说明

搞定,木有对 www.baidu.com 的连接了;;很好,连接都关闭了。

结尾

连接的关闭,要补上 closeIdleConnections 的调用;或者是直接对 connection.close 的方法。 那么为什么 apache 的 common-httpclient不直接关闭呢。实际上,这个是基于效率的考虑,在网络连接的时候, http连接的创建是耗时的,而框架是希望同一个connection可以复用的。但我们在使用的时候,每次都 new HttpClient 的方式,也就导致了复用不了;在这个情况下,还是干脆关闭吧;

如果并发过高,不进行关闭的话,应用会linux下运行会出现 too many open files 的错误。。

另外:考虑升级了,升级到 httpcomponents 的 httpclient

<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpclient</artifactId>
  <version>4.5.3</version>
</dependency>

参考资料

httpclient源码分析-如何重用连接

转载于:https://my.oschina.net/u/140938/blog/853832

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值