httpclient连接池管理,你用对了?

文章插图
一、前言为何要用http连接池那?因为使用它我们可以得到以下好处:
因为使用它可以有效降低延迟和系统开销 。如果不采用连接池,每当我们发起http请求时,都需要重新发起Tcp三次握手建立链接,请求结束时还需要四次挥手释放链接 。而链接的建立和释放是有时间和系统开销的 。另外每次发起请求时,需要分配一个端口号,请求完毕后在进行回收 。
使用链接池则可以复用已经建立好的链接,一定程度的避免了建立和释放链接的时间开销 。
二、连接池使用
public static void init() {//1.创建连接池管理器PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(60000,//1.1TimeUnit.MILLISECONDS);connectionManager.setMaxTotal(1000);//1.2connectionManager.setDefaultMaxPerRoute(50);//1.3//2.创建httpclient对象httpClient = HttpClients.custom().setConnectionManager(connectionManager)//2.1.disableAutomaticRetries()//2.2.build();}
如上代码1,我们创建了一个连接池管理器,ClientConnectionPoolManager会维护每个路由维护和最大连接数限制 。默认情况下,此实现将为每个给定路由创建不超过2个并发连接,并且总共不超过20个连接 。对于许多现实应用程序,这些限制可能证明过于严格 。但是,我们可以自由来调整连接限制 。
另外构造函数中可以设置持久链接的存活时间TTL(timeToLive),其定义了持久连接的最大使用时间,超过其TTL值的链接不会再被复用 。
如上代码1.1我们设置TTL为60s(Tomcat服务器默认支持保持60s的链接,超过60s,会关闭客户端的链接) 。代码1.2我们设置连接器最多同时支持1000个链接,代码1.3设置每个路由最多支持50个链接 。注意这里路由是指IP+PORT或者指域名 。如果使用域名来访问则每个域名有自己的链接池,如果使用IP+PORT访问,则每个IP+PORT有自己的链接池 。
如上代码2我们基于连接池管理器创建了一个httpClient对象,下面我们就可以使用它发起http请求了 。
CloseableHttpResponse response = null;try {//3.创建请求对象final HttpGet httpGet = new HttpGet("http://127.0.0.1:8080/test");RequestConfig.Builder builder = RequestConfig.custom();builder.setSocketTimeout(3000)//3.1设置客户端等待服务端返回数据的超时时间.setConnectTimeout(1000)//3.2设置客户端发起TCP连接请求的超时时间.setConnectionRequestTimeout(3000);//3.3设置客户端从连接池获取链接的超时时间httpGet.setConfig(builder.build());//4.发起请求response = httpClient.execute(httpGet);//5.成功则解析结果if (200 == response.getStatusLine().getStatusCode()) {String strResult = EntityUtils.toString(response.getEntity());System.out.println(strResult);}} catch (ClientProtocolException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {//5.回收链接到连接池if (null != response) {try {EntityUtils.consume(response.getEntity());} catch (IOException e) {e.printStackTrace();}}}
如上代码3创建了一个HttpGet对象,并创建RequestConfig对象来设置请求参数 。代码3.3设置客户端从连接池获取链接的超时时间,如果在该时间内没能从连接池获取到连接,则抛出
ConnectionPoolTimeoutException异常 。
代码3.2设置客户端发起TCP连接请求的超时时间,也就是创建TCP连接时候等待的时间,如果该时间内还没完成TCP三次握手,则抛出ConnectTimeoutException异常 。
代码3.1设置客户端等待服务端返回数据的超时时间,也就是请求发出去后,如果等待该时间服务端还没返回结果,则抛出SocketTimeoutException异常 。
代码4则发起http请求,代码5发现请求OK,则使用自带工具类EntityUtils.toString解析返回值(内部读取流结束后,会自动返还链接到连接池)
代码5则当请求结束后做一个兜底链接归还(如果返回状态值不是200,则需要在这里处理链接归还),注意这里不能调用response.close();因为其不是归还链接到连接池,而是关闭链接 。
三、总结本文简单介绍了如何使用链接池,使用连接池时需要注意合理设置最大链接数和每个路由(比如域名)对应的链接数,另外特别需要注意设置
setConnectionRequestTimeout参数,其决定了从连接池拿链接的超时时间 。
另外需要注意使用链接池时,请求结果回来后,要记得归还链接,如果链接得不到归还,则首先会把连接池打满,然后新来的请求从连接池拿不到链接会抛出
ConnectionPoolTimeoutException异常 。
另外归还链接不要调用response对象的close()方法,因为其是关闭链接,而不是把链接返回到链接池 。需要调用EntityUtils中方法或者自己从response.getEntity().getContent()获取流,读取完毕(读取完毕后会自动归还链接)或者不读取时主动调用流的close()来显示归还链接到连接池 。
推荐阅读
- 手淘首页流量如何入池 淘宝新品怎么入池
- 说起来 TCP 的连接与释放真是个浪漫的故事呢!
- Win10电脑蓝牙连接手机播放音乐
- 车子停久了,蓄电池会亏电,正确的方法是这样的
- 一篇文章搞定Python连接mysql数据库模块PyMySQL
- 分享几款免费的连接Linux的使用工具
- 手表换电池多少钱?石英表电池多久换一次?
- 知乎千万级高性能长连接网关是如何搭建的
- 锂电池|丈夫舍身救妻火灾系锂电池自燃引发 网友直呼可怕:电动车不要推回家充
- 锂电池行业术语介绍,你了解多少?