| date : 2017.3.7 |linux
apache 提供的common-httpclient (3.1 的版本),在调用httpclient的时候,是很方便的,在实际的项目中,调用第三方服务,也常常使用;此次在客户现场发现了一个问题;apache
咱们调用第三方的服务,第三方服务在监控链接的时候,提到咱们发起的链接有许多的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 吧;源码分析
JPS看看,咱的进程ID测试
来吧,检查一下进程 windons 下面的命令:netstat -ano|find "20168" |find "61."
计数命令:netstat -ano|find "20168" |find "61." /c
this
100个链接哦,,还都是 CLOSE_WAIT的; 好吧;就说明咱们上面脚本中循环了100个,就压根没有是否端口呀。。。.net
为啥,,这个是为啥。已经调用了 releaseConnection() ;难道是releaseConnection()的问题,要不看看的呗。 GetMethod --> HttpMethodBase --> HttpConnection --> HttpConnectionManager 好吧,这里是个接口。咋整,从 HttpClient入口,发现默认是使用 SimpleHttpConnectionManager ,走起; 源码以下:
看到了,坑的地方来了;
if(this.alwaysClose)
这个值,默认是false的哦。。并且,貌似还没地方赋值的呢。。换句话说,默认是 finishLastResponse,查看这个方法,卧槽,厉害了,只是清理了 inputStream 呢。但链接木有关闭啊; 要关闭链接怎么办?咱们本身来关闭?往下翻了翻,额,有个closeIdleConnections 的方法;这个的源码看了一下,额,关闭在Nms以前的链接呢。。恩。这个能够用; 试试看;debug
新的测试代码以下:就补充了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>