为什么要使用连接池?
Druid是我们最常听到的连接池,之前提到一个问题,如果无限创建连会怎么样?一般来说数据库都会限制连接数,连接保持意味着占用一部分宝贵的资源,比如线程内存。
前面的demo中也可以看到在使用完毕Connection后,会调用close方法去关闭这个连接,并且释放资源。
但是会引入一个新的问题,连接的创建和关闭是一个不稳定的操作,在某些客户环境下创建一个连接并建立通信要花费好几秒,如果每次查询都重新创建连接,这样的性能损耗累积起来实在太大。
所以如果我们创建连接后,持有这个连接进行多次查询这样就能节省一大块时间。这就是连接复用。
这就是连接池的作用,减少连接创建开销,尽可能在需要查询时提供可用的连接。
连接池的工作原理
连接池要实现的目标除了刚才说的连接复用,也会带来一个问题,当空闲的时候连接一直维持着,这样数据库端的资源也没有释放。
因此一个好的连接池必须具备以下几个特点:
能连接复用减少创建开销
能控制连接数量减少对数据库的影响
能够值守无需创建随时可用
有了这三条准则,我们可以自己实现一个连接池,不信?来试试:
创建一个池子;
我们给池子创建10个初始连接(initSize),提供给业务使用,通常也够用了;
为了应付高峰查询,我们允许连接池短暂的存在100个连接(maxSize),但是到低谷都要关闭;
连接一般是tcp或者http等实现的,它是有生命周期的比如socketTimeout,会被数据库或者网络波动影响关闭,因此我们需要一个连接检查器(连接校验)检查连接是否畅通;
如果空闲时突然来了一个查询,此时连接都被数据库关闭了,连接检查后(连接前校验),还是要重新创建,这个开销就不可避免,所以我们可以在空闲的时候定时检查(空闲检测testWhileIdle)一下连接,如果关闭就重新创建一个放在池子里;
为了防止连接占有资源,我们需要在空闲的时候释放至最小连接数(minIdle),需要配置一个空闲时间(idleTime),达到空闲时间后连接池主动关闭;
这个过程,大家应该看到一些我们熟悉的概念了,比如连接池大小、空闲检测、连接检查器等;实际上所以的连接池基本上都会具备这些特点,也可以自定义去设置参数大小以满足业务的真实需求;
常见的连接池
在Druid之前,我们使用的是经典的DBCP连接池,但是DBCP性能不佳,改用了高性能的Druid。
现在比较常用还有HikiraCP等。