连接池
连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用。
解释:连接池就是数据库、JDBC使用的一种创建和管理连接的缓冲池的技术,就是把数据库与服务器的那些增删查改需要的连接放进一个缓冲池中使用,大大提高性能和效率的一个手段。
使用背景
在我们的开发中,常常会用到要访问数据库的数据,通过JDBC,建立数据库连接,执行SQL,关闭连接,等等一系列操作。
此中,连接数据库、打开数据库是一件耗资源、耗时间的工作,开发中如果频繁使用必定会浪费大量资源,急剧降低系统的性能。
所以我们会使用连接池这一技术手段解决这一问题。很多应用程序服务器比如JBoss,Weblogic,tomcat等都提供了连接池这项技术,所以我们开发使用起来很方便。
技术思想
把数据库连接作为对象存储在一个Vector对象中,数据库连接建立后,不同的数据库访问请求就可以共享这些连接,由此,我们复用了这些连接,就可以极大的节省系统资源和时间。
工作原理
- 服务器启动时建立数据库连接池对象。
- 创建初始的数据库池连接中连接的数量,即空闲连接数,并一直会维持不少于此数目的池连接。
- 客户端程序使用连接时,池驱动程序会返回一个未使用的池连接,并将其表记为“忙”。如果当前没有空闲连接,池驱动程序就会新建一定数量的连接,新建的连接数量是由配置参数决定的。
- 当使用的池连接调用完成后,池驱动程序就将此连接表记为“空闲”,然后有其他使用连接时就可以调用这些连接了。
- 服务器停止或维护期间,释放数据库连接池对象,并释放所有连接。
实现方案
连接池类----BDConnectionPool 连接池管理类----DBConnectionPoolManager
连接池管理类是连接池类的外覆类—wrapper ,符合单例模式,就是系统里只能有一个连接池管理类的实例。
连接池管理类的功能:
- 装载并注册特定数据库的JDBC驱动程序
- 根据文件配置信息,创建连接池对象
- 跟踪客户端使用连接情况,更好的管理连接池的使用和管理
- 连接池与其实例可以取别名并映射
具体方案:
连接池使用集合装载数据库连接,返回的Connection是原始Connection的代理
当调用close方法时,不是真正关闭连接,而是把它代理的Connection的对象放回连接池中,等待下一次重复利用。
(这里有个逻辑和物理的删除或关闭的概念,简单来说,逻辑上的就是我们说的让它咋样就咋样,逻辑上的一种说法。而物理上的就是真的在内存或空间里剔除,清除了就真的没了)
介绍几个常用的连接池
DRUID
DBCP
C3P0
proxool
JDNI
这些是常用的开源数据库连接池,以下一一做解释:
DBCP
dbcp非常常见了,用过Apache Tomcat的就要知道,Apache Tomcat服务器给我们提供的连接池内部就是DBCP。
一般用DataSource获取连接的话,通常获取连接到代码和驱动特定的DataSource是紧耦合的,而且除了DataSource的实现类,剩下的代码都一样。所以DBCP提供的DataSource实现成为了应用程序和不同的JDBC驱动间的一个抽象层。
使用DBCP数据源的步骤为:
- 导入commons-dbcp.jar 和 commons-pool.jar 和 common-collections.jar包
- 读取配置文件
- 获取BasicDataSourceFactory对象
- 创建DataSource对象
以hibernate为例:
hibernate是有自带连接池的,它的连接池配置文件里只有一个 hibernate.connection.pool_size 1 表明hibernate的自带连接池的连接数量就一个,而以上四个都支持hibernate的连接池操作
dbcp在hibernate的配置:
<property name="dbcp.maxActive">100</property>
<property name="dbcp.whenExhaustedAction">1</property>
<property name="dbcp.maxWait">60000</property>
<property name="dbcp.maxIdle">10</property>
<property name="dbcp.ps.maxActive">100</property>
<property name="dbcp.ps.whenExhaustedAction">1</property>
<property name="dbcp.ps.maxWait">60000</property>
<property name="dbcp.ps.maxIdle">10</property>
C3P0
C3P0是一个开源的连接池,实现数据源和JNDI的绑定,也是异步操作的,用的多的还是hibernate,spring也相对多一些,突出特点是有自动回收空闲连接的功能。
proxool
proxool是sourceforge下的一个开源项目,这个连接池突出的特点是提供了监控的功能,能更方便发现连接是否泄露。proxool只能管理自己产生的连接。
大概配置信息:
<!-- proxool自动侦察各个连接状态的时间间隔(毫秒),侦察到空闲的连接就马上回收,超时的销毁-->
<house-keeping-sleep-time>90000</house-keeping-sleep-time>
<!-- 指因未有空闲连接可以分配而在队列中等候的最大请求数,超过这个请求数的用户连接就不会被接受-->
<maximum-new-connections>20</maximum-new-connections>
<!-- 最少保持的空闲连接数-->
<prototype-count>5</prototype-count>
<!-- 允许最大连接数,超过了这个连接,再有请求时,就排在队列中等候,最大的等待请求数由maximum-new-connections决定-->
<maximum-connection-count>100</maximum-connection-count>
<!-- 最小连接数-->
<minimum-connection-count>10</minimum-connection-count>
JDNI
JDNI连接池的数据源概念是Tomcat 4.1.27开始,服务器上直接增加了个数据源(datasource)的配置选项,直接在服务器上配置数据源连接池即可。DataSource是被绑在了JDNI树上的,客户端通过树上绑定的Datasource的名字获得DataSource。
hibernate只要查找到此JDNI数据源就可以了。
应用服务器将连接池显示为JDNI绑定数据源,它还是Java.jbdc.DataSource 的一个实例。
配置文件:
hibernate.connection.datasource=java:/comp/env/jdbc/JNDI_NAME
hibernate.transaction.factory_class = org.hibernate.transaction.JTATransactionFactory
hibernate.transaction.manager_loopup_class=org.hibernate.transaction.JBossTransactionManagerLookup
hibernate.dialect=org.hibernate.dialect.MySQLDialect
一些细节与比较
- hibernate3.0中,不支持DBCP了。
- DBCP没有自动回收空闲连接的功能,但C3P0有自动回收空闲连接功能。
- 性能上,proxool大于C3P0的,而C3P0大于等于DBCP(大部分大于,但也有性能相当的情况)
- 稳定性上,DBCP是大于等于C3P0的,C3P0大于proxool。
- 一般来说C3P0占用的资源比较大,效率也不是很高
- C3P0和proxool能更好的支持高并发,但是稳定性又稍低于DBCP,所以用连接池时可以多注意项目需求。
- 目前最好用的应该就是druid了,它是阿里开源的一个项目。是java中最好的数据库连接池,提供强大的监控合扩展功能,可以替换DBCP和C3P0。高效,功能强大,可扩展性高 的优点。建议使用druid
- Druid 是性能最好的数据库连接池,tomcat-jdbc 和 druid 性能接近。
- proxool 在激烈并发时会抛异常,完全不靠谱。
- c3p0 和 proxool 都相当慢,慢到影响 sql 执行效率的地步。
- bonecp 性能并不优越,采用 LinkedTransferQueue 并没有能够获得性能提升。
- jboss-datasource 虽然稳定,但是性能很糟糕
以下是各大连接池的测试结果:
总结
数据库连接池极大的提升了我们的开发项目的效率和减少时间耗费。一些连接池还有其特殊功能帮助开发我们的项目,所以要清楚哪些连接池有那些功能,支持不支持当前系统,也是需要学习和理解的。