高性能httpClient

最近工作中遇到了一个rpc高频调用出现

java.net.BindException: 地址已在使用

问题,由于线下测试的时候并没有庞大的数据量来支撑,这个问题并没有在测试阶段被发现。研究发现,出现改问题的主要是因为短时间内OS的socket被迅速烧光,程序初启动前20秒内一切正常,后面开始狂抛此类异常。之前的http调用主要使用httpclient框架实现,代码如下:

HttpClient httpClient = HttpClient();
GetMethod method = GetMethod();
httpClient.getHttpConnectionManager().getParams().setConnectionTimeout();
httpClient.getHttpConnectionManager().getParams().setSoTimeout();
{
    httpClient.executeMethod(method);
} (Throwable t) {
    System..println();
}
String responseBodyAsString = ;
{
    responseBodyAsString = method.getResponseBodyAsString();
    System..println();
} (Throwable t) {
    System..println();
}

该段代码被封装在一个普通的发放内 每次调用传入相应的URL和参数即可。正常情况下并不会出现什么问题。深入分析代码后发现httpclient 对象内部会默认创建一个HttpClientParams对象和SimpleHttpConnectionManager对象 manager 对象内部会持有一个connection 这里可以类比与jdbc 中的connection。非常蛋疼的一点是这个连接在执行完请求后并不会被立即关闭。SimpleHttpConnectionManager对象中有这样一句

alwaysClose = ;

这意味着该连接默认不会被关闭。当然随着方法被执行完,这些对象就成了垃圾数据会被gc掉。但是底层资源的释放速度可就不好说了。恰恰在于上面的那一大段代码处于方法里,在高频调用这个方法时,会创建超多的底层tcp连接。下面的故事就不用多说了。

可能有人会想到既然没关掉这个连接那就想办法关掉就是了 。本人初期也是这么想的 关掉不就行了吗。网上荡了一份代码

HttpClient httpClient = HttpClient(HttpClientParams(),SimpleHttpConnectionManager());

据说这样就可以保证连接会断开(客户端断开),然并卵~~~

继续坑,既然断掉也不行那就复用好吧,翻看源码发现

HttpConnectionManager

这个接口的实现有三个(包含SimpleHttpConnectionManager),其中一个叫做

MultiThreadedHttpConnectionManager

发现了曙光,为多线程准备的ConnectionManager .搞来玩玩。  于是乎就出现了以下的代码

MultiThreadedHttpConnectionManager =MultiThreadedHttpConnectionManager();

{
    .getParams().setMaxTotalConnections();
    .getParams().setDefaultMaxConnectionsPerHost();
}

需要指出的是,这个管理器可以管理多个连接池,底层是一个Map key为host Value 则是connectionPool

setDefaultMaxConnectionsPerHost  就是指每个host允许建立的最多连接数。不需要太多!

结合

new HttpClient(new HttpClientParams(),new SimpleHttpConnectionManager(true));

想到了什么 ?

是的 :

new HttpClient(new HttpClientParams(),cm);

下面的代码原封不动,但是要主要的是获取完数据后记得调用 

method.releaseConnection();

正所谓好借好还,再借不难嘛

这些连接会被管理器揣在兜里需要的时候问他申请,有就给你,没有嘛一边呆着等

个人猜测是借助了http连接的keepAlive 特性。实现多个请求复用一个通道。





注:本文借鉴了多篇该领域的文章,同时结合自身的一些实践心得整理而成

你可能感兴趣的:(httpclient,连接池)