随着微服务的流行,服务之间的http调用越来越多,遇到的问题也比较多,写这边文章的目的也是将自己遇到的坑和解决方案跟大家分享

一、为什么要用Http连接池

1、降低延迟:如果不采用连接池,每次连接发起Http请求的时候都会重新建立TCP连接(经历3次握手),用完就会关闭连接(4次挥手),如果采用连接池则减少了这部分时间损耗,别小看这几次握手,本人经过测试发现,基本上3倍的时间延迟

2、支持更大的并发:如果不采用连接池,每次连接都会打开一个端口,在大并发的情况下系统的端口资源很快就会被用完,导致无法建立新的连接

二、代码

1、PoolingHttpClientFactory.java连接池管理类,支持http与https协议

import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.config.RequestConfig.Builder;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; public class PoolingHttpClientFactory {
private int timeOut = 30000;
private int maxConnectionTotal = 400;
private int maxConnectionPerRoute = 400;
private PoolingHttpClientConnectionManager poolConnManager;
private Builder builder;
private RequestConfig requestConfig;
private HttpClientBuilder hcb; private static PoolingHttpClientFactory pooling = new PoolingHttpClientFactory(); private PoolingHttpClientFactory() {
poolConnManager = createConnectionManager();
builder = RequestConfig.custom();
if(timeOut != 0){
builder.setConnectionRequestTimeout(timeOut).setConnectTimeout(timeOut).setSocketTimeout(timeOut);
}
requestConfig = builder.build();
hcb = HttpClients.custom().setConnectionManager(poolConnManager).setDefaultRequestConfig(requestConfig);
} public static PoolingHttpClientFactory getInstance() {
if (pooling == null) {
pooling = new PoolingHttpClientFactory();
}
return pooling;
} public CloseableHttpClient createHttpClient(){
CloseableHttpClient httpClient = hcb.build();
return httpClient;
} public PoolingHttpClientConnectionManager createConnectionManager(){
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSocketFactory())
.build(); PoolingHttpClientConnectionManager poolConnManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
if(maxConnectionTotal != 0){
poolConnManager.setMaxTotal(maxConnectionTotal);
}
if(maxConnectionPerRoute != 0){
poolConnManager.setDefaultMaxPerRoute(maxConnectionPerRoute);
}
return poolConnManager;
} public void setTimeOut(int timeOut) {
this.timeOut = timeOut;
}
public void setMaxConnectionTotal(int maxConnectionTotal) {
this.maxConnectionTotal = maxConnectionTotal;
}
public void setMaxConnectionPerRoute(int maxConnectionPerRoute) {
this.maxConnectionPerRoute = maxConnectionPerRoute;
}
}

2、连接池消费类:TestClient.java

import com.alibaba.fastjson.JSON;
import org.apache.commons.io.IOUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.testng.annotations.Test;
import java.io.IOException;
import java.io.InputStream; public class TestClient {
PoolingHttpClientFactory connManager; public Object get(String path){
CloseableHttpClient httpClient = PoolingHttpClientFactory.getInstance().createHttpClient(); //创建实例对象
HttpGet httpget = new HttpGet(path);
String json=null;
CloseableHttpResponse response=null;
try {
response = httpClient.execute(httpget);
InputStream in=response.getEntity().getContent();
json= IOUtils.toString(in, "Utf8");
in.close();
} catch (UnsupportedOperationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(response!=null){
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return JSON.parse(json);
}
public Object post(String path){
CloseableHttpClient httpClient = PoolingHttpClientFactory.getInstance().createHttpClient(); //创建实例对象
HttpPost httppost = new HttpPost(path);
String json=null;
CloseableHttpResponse response=null;
try {
response = httpClient.execute(httppost);
InputStream in=response.getEntity().getContent();
json= IOUtils.toString(in, "Utf8");
in.close();
} catch (UnsupportedOperationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(response!=null){
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return JSON.parse(json);
}

三、原理及注意事项

连接池中连接都是在发起请求的时候建立,并且都是长连接

TestClient.java中的in.close();作用就是将用完的连接释放,下次请求可以复用,这里特别注意的是,如果不使用in.close();而仅仅使用response.close();结果就是连接会被关闭,并且不能被复用,这样就失去了采用连接池的意义。

连接池释放连接的时候,并不会直接对TCP连接的状态有任何改变,只是维护了两个Set,leased和avaliabled,leased代表被占用的连接集合,avaliabled代表可用的连接的集合,释放连接的时候仅仅是将连接从leased中remove掉了,并把连接放到avaliabled集合中

httpclient4.5 连接池的封装的更多相关文章

  1. Go/Python/Erlang编程语言对比分析及示例 基于RabbitMQ.Client组件实现RabbitMQ可复用的 ConnectionPool(连接池) 封装一个基于NLog+NLog.Mongo的日志记录工具类LogUtil 分享基于MemoryCache(内存缓存)的缓存工具类,C# B/S 、C/S项目均可以使用!

    Go/Python/Erlang编程语言对比分析及示例   本文主要是介绍Go,从语言对比分析的角度切入.之所以选择与Python.Erlang对比,是因为做为高级语言,它们语言特性上有较大的相似性, ...

  2. HttpClient4.3 连接池参数配置及源码解读

    目前所在公司使用HttpClient 4.3.3版本发送Rest请求,调用接口.最近出现了调用查询接口服务慢的生产问题,在排查整个调用链可能存在的问题时(从客户端发起Http请求->ESB-&g ...

  3. 在Tomcat中配置连接池和数据源

    1.DataSource接口介绍 (1)DataSource 概述 JDBC1.0原来是用DriverManager类来产生一个对数据源的连接.JDBC2.0用一种替代的方法,使用DataSource ...

  4. HttpClient4.X 升级 入门 + http连接池使用

    转载请注明出处,谢谢~ http://blog.csdn.net/shootyou/archive/2011/05/12/6415248.aspx 在一次服务器异常的排查过程当中(服务器异常排查的过程 ...

  5. nodejs 封装mysql连接池

    写在前面的 在nodejs后台代码中,我们总是会和数据库打交道 然而,每次都要写数据库的配置以及连接和断开,不胜其烦 我就封装了一个连接池模块,不足之处还请多多批评 上代码 一下是写在mysqls.j ...

  6. Redisclient连接方式Hiredis简单封装使用,连接池、屏蔽连接细节

    工作须要对Hiredis进行了简单封装,实现功能: 1.API进行统一,对外仅仅提供一个接口. 2.屏蔽上层应用对连接的细节处理: 3.底层採用队列的方式保持连接池,保存连接会话. 4.重连时採用时间 ...

  7. HttpClient4.5.2 连接池原理及注意事项

    随着微服务的流行,服务之间的http调用越来越多,遇到的问题也比较多,写这边文章的目的也是将自己遇到的坑和解决方案跟大家分享 一.为什么要用Http连接池 1.降低延迟:如果不采用连接池,每次连接发起 ...

  8. 简易高重用的jdbcutils工具封装实现类以及简易连接池实现

    因为如今发现做个小项目都是导入n多的依赖包,非常烦琐,仅仅想快点开发完一个个的小需求项目,这个时候真心不想用框架,仅仅能自己写个jdbcutils,尽管网上有非常多有apache的,阿里的,可是感觉用 ...

  9. golang 基于channel封装资源池(可用于封装redis、mq连接池)

    package pool import ( "errors" "io" "sync" "time" ) var ( Er ...

随机推荐

  1. 处理编译错误"0" is an invalid value for the "DebugInformation" parameter of the "DCC" task.

    在安装一个从XE6复制到XE4的控件时出现编译错误: [MSBuild Error] "0" is an invalid value for the "DebugInfo ...

  2. Linux 下安装mysql 8.0.11(CentOS 7.4 系统)

    CentOS 7 自带MariaDB (前mysql开发工程师开发的,因此与吗,mysql 有很多相似之处) 1.检查卸载自带的MariaDB rpm -qa|grep mariadb //查询出来已 ...

  3. [学习]Windows server 使用控制台时容易卡死的解决方法

    公司使用Windows server 下面的 cmd 命令行 控制台打开某一个 bat 文件的方式 进行后台使用.. 但是经常发现在winserver 2016 时 遇到卡死的情况, 今天中午我再进行 ...

  4. [转帖]22个必须学习的Linux安全命令

    22个必须学习的Linux安全命令 http://os.51cto.com/art/201808/581401.htm Linux系统的安全性涉及很多方面,从设置帐户到确保用户合法,限制比完成工作所需 ...

  5. Windows下CURL扩展无效之终极解决办法。

    本地开发环境使用WAMP快速搭建,在使用PHP的CURL时可能会存在无法载入情况,这里提供终极解决方法. 1.在php.ini配置文件中启用 php_curll.dll 扩展: (环境已经自动附带 l ...

  6. React之智能组件和木偶组件

    智能组件 VS 木偶组件 在 React + Redux 结合作为前端框架的时候,提出了一个将组件分为“智能”和“木偶”两种 智能组件:它是数据的所有者,它拥有数据.且拥有操作数据的action,但是 ...

  7. POJ3177_Redundant Paths

    给你一个无向图,求至少加入多少条边,使得整个图是双联通的. 通过枚举题意,发现重边是不算的,直接去掉. 首先把那些边是桥计算出来,把位于同一个连通分量里面的点缩成一个点(并查集),然后计算缩点后有多少 ...

  8. 状压DP入门详解+题目推荐

    在动态规划的题型中,一般叫什么DP就是怎么DP,状压DP也不例外 所谓状态压缩,一般是通过用01串表示状态,充分利用二进制数的特性,简化计算难度.举个例子,在棋盘上摆放棋子的题目中,我们可以用1表示当 ...

  9. Git常用的几个命令

    标签(空格分隔): Git 在本地文件系统中新建目录,放置你的工程: mk dir parkk cd parkk //进入该目录 git init //初始化自己的仓库,默认名称为master 在仓库 ...

  10. hbase 分页过滤(新老API的差别)

    在hbase2.0以前分页过滤必须以上一次的最后一行+空字节数组作为下一次的起始行, 因为scan扫描的时候是包含起始行的,为了既能准确定位起始行,但又不重复把上一次的最末一行加入下一页, 所以,权威 ...