连接池

碎碎念  

  其实所谓的“连接池”,个人观点是一种在工程实践中以空间换时间的优化方案。

  我们在实际的开发中,常见的资源表现形式:一种是存储(内存+磁盘存储)资源,还有是IO(磁盘IO+网络IO)资源,另外当然还有操作系统CPU的调度/计算等等。

  而在实际中,存储资源相对于IO及计算来说便宜很多,比如说当我们的服务遇到瓶颈的时候,最直接的方案就是升级机器、增加存储,先让线上的服务恢复稳定然后再去考虑优化。

什么是连接池

  

 

  连接池其实是基于“连接”的概念而来的。所谓连接,在绝大多数情况下其实就是Client-Server模式的一种资源传输的通道。当客户端与服务端想要创建通信时,首先需要在二者之间创建连接(TCP、UDP),然后二者进行数据通信、资源传输等等操作。

  而客户端与服务端每创建一次连接需要很多次的网络IO操作,期间也会使用CPU的计算、调度开销。而且实际中如果二者需要长时间不断创建、断开链接资源,会浪费大量的CPU调度资源。

  而如果使用连接池的话:我们在客户端与服务端之间“提前”维护好“固定数量的链接”,这些链接整合到一起会占用操作系统的内存资源,但是这个连接池中的连接使用完以后会重新放入连接池中而不是直接断开,等需要处理后续的业务的时候还能使用原来的连接资源,这样就大大降低了网络IO的开销(因为每次创建、释放连接的时候都需要握手、挥手的过程);而且上面也提到了内存资源相对于IO及计算资源相对便宜一些,虽然连接池占用了一定的内存资源,但是通过这种方式我们节约了网络IO的开销,在很大程度上能使系统保持稳定。

  常见的连接池:数据库连接池、redis连接池、HTTP连接池;当然代码级别中我们常见的有进程池、线程池(线程与进程严格意义上不算是连接啦,是操作系统中的资源)等等。

HTTP连接池使用前提

HTTP连接池使实现的效果其实是连接可以复用,那复用的前提是连接一直存在,所以:需要服务端与客户端都支持长链接!只要有一方断开了连接那么这个连接就不能复用了!

实际业务中的一个案例 

HTTP连接池的参数实验(一)

默认值说明

  这里用一个例子简单说明一下:

案例一:

客户端连接池参数如下:

启动项目:

运行 TestLong 这个函数,可以看到,客户端只用了一个TCP连接去处理请求:

案例二:

客户端连接池设置参数如下:

再运行 TestLong 结果如下:

在客户端程序运行期间,也可以使用netstat命令看看效果:

案例三:

客户端连接池设置如下:最大连接数设置为2,两个空闲的配置为1
 

再运行 TestLong 结果如下:也就是说,超过了最大连接数,设置了空闲连接数的话,会自动再开一个链接处理请求,而不是等“最大连接数的计数-1”~

案例四:多个host连接(一)

MaxIdleConns vs MaxIdleConnsPerHost 两个连接池

如下源码,先检查 PerHost 的池子有没有满,再检查总的池子有没有满。也就是说,MaxIdleConns设置不合理,会对MaxIdleConnsPerHost有影响。

客户端参数配置如下:

现在需要运行2个服务端:

然后客户端执行 TestLongLong 结果如下,都有不断重建的情况:

案例五:多个host连接(二)

客户端这样配置连接池参数:

现在需要运行2个服务端:

然后客户端执行 TestLongLong 结果如下,两个客户都端维持一个链接:

 

HTTP连接池的参数实验(二)客户端连接复用需要Client与Server同时支持

服务端不支持长链接的情况

任何一方主动关闭连接,连接就无法复用。

客户端参数:

运行服务端的8088:(会主动断开链接!)

然后运行一下8087(不会主动断开链接):

然后客户端执行 TestLongShort 结果如下,8087这个客户端还是维持一个链接:

很明显:8088端口服务端每次链接都断开的话~客户端每次会用不同的链接:

客户端不获取响应体数据链接也无法复用

连接池设置的没问题:

但是,客户端不获取响应数据:

看一下8087端口的结果:最终还是创建了好多个链接!!!

参考文章

~~~