一.数据库连接池概述
数据库连接的建立是一种耗时、性能低、代价高的操作,频繁的数据库连接的建立和关闭极大的影响了系统的性能。数据库连接池是系统初始化过程中创建一定数量的数据库连接放于连接池中,当程序需要访问数据库时,不再建立一个新的连接,而是从连接池中取出一个已建立的空闲连接,使用完毕后,程序将连接归还到连接池中,供其他请求使用,从而实现的资源的共享,连接的建立、断开都由连接池自身来管理。
数据库连接池为系统的运行带来了以下优势:昂贵的数据库连接资源得到重用;减少了数据库连接建立和释放的时间开销,提高了系统响应速度;统一的数据库连接管理,避免了连接资源的泄露。
数据库连接池运行机制:
系统初始化时创建连接池,程序操作数据库时从连接池中获取空闲连接,程序使用完毕将连接归还到连接池中,系统退出时,断开所有数据库连接并释放内存资源。
二.主流数据库连接池比较
常用的主流开源数据库连接池有C3P0、DBCP、Tomcat Jdbc Pool、BoneCP、Druid等
(1)、C3p0
开源的JDBC连接池,实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate、Spring等。单线程,性能较差,适用于小型系统,代码600KB左右。
(2)、DBCP (Database Connection Pool)
由Apache开发的一个Java数据库连接池项目, Jakarta commons-pool对象池机制,Tomcat使用的连接池组件就是DBCP。单独使用dbcp需要3个包:common-dbcp.jar,common-pool.jar,common-collections.jar,预先将数据库连接放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完再放回。单线程,并发量低,性能不好,适用于小型系统。
(3)、Tomcat Jdbc Pool
Tomcat在7.0以前都是使用common-dbcp做为连接池组件,但是dbcp是单线程,为保证线程安全会锁整个连接池,性能较差,dbcp有超过60个类,也相对复杂。Tomcat从7.0开始引入了新增连接池模块叫做Tomcat jdbc pool,基于Tomcat JULI,使用Tomcat日志框架,完全兼容dbcp,通过异步方式获取连接,支持高并发应用环境,超级简单核心文件只有8个,支持JMX,支持XA Connection。
(4)、BoneCP
官方说法BoneCP是一个高效、免费、开源的Java数据库连接池实现库。设计初衷就是为了提高数据库连接池性能,根据某些测试数据显示,BoneCP的速度是最快的,要比当时第二快速的连接池快25倍左右,完美集成到一些持久化产品如Hibernate和DataNucleus中。BoneCP特色:高度可扩展,快速;连接状态切换的回调机制;允许直接访问连接;自动化重置能力;JMX支持;懒加载能力;支持XML和属性文件配置方式;较好的Java代码组织,100%单元测试分支代码覆盖率;代码40KB左右。
(5)、Druid
Druid是Java语言中最好的数据库连接池,Druid能够提供强大的监控和扩展功能,是一个可用于大数据实时查询和分析的高容错、高性能的开源分布式系统,尤其是当发生代码部署、机器故障以及其他产品系统遇到宕机等情况时,Druid仍能够保持100%正常运行。主要特色:为分析监控设计;快速的交互式查询;高可用;可扩展;Druid是一个开源项目,源码托管在github上。
三.Spring集成配置与JNDI配置
下面针对每一种连接池的使用方法,在开发中如何配置给出spring集成配置和在tomcat的conf/context.xml文件中配置2种方式,限于篇幅只给出基本参数,详细参数可自行研究。以下主要讲推荐用的Druid和Tomcat Jdbc Pool的配置。
(1)、 阿里Druid连接池
Maven依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.28</version>
</dependency>
1)Spring集成配置方式
spring数据源配置
<!--SpringDruid 数据源配置-->
<beanid="dataSource"class="com.alibaba.druid.pool.DruidDataSource"init-method="init"destroy-method="close">
<!-- 基本属性 url、user、password -->
<propertyname="url"value="${jdbc.url}"/>
<propertyname="username"value="${jdbc.username}"/>
<propertyname="password"value="${jdbc.password}"/>
<!-- 配置初始化大小、最小、最大 -->
<propertyname="initialSize"value="1"/>
<propertyname="minIdle"value="1"/>
<propertyname="maxActive"value="20"/>
<!-- 配置获取连接等待超时的时间 -->
<propertyname="maxWait"value="60000"/>
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<propertyname="timeBetweenEvictionRunsMillis"value="60000"/>
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<propertyname="minEvictableIdleTimeMillis"value="300000"/>
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<propertyname="poolPreparedStatements"value="true"/>
<propertyname="maxPoolPreparedStatementPerConnectionSize"value="20"/>
<!-- 配置监控统计拦截的filters,去掉后监控界面sql无法统计 -->
<propertyname="filters"value="stat"/>
</bean>
web.xml配置
<!--druid WebStatFilter用于采集web-jdbc关联监控的数据-->
<filter>
<filter-name>DruidWebStatFilter</filter-name>
<filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
<init-param>
<param-name>exclusions</param-name>
<param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>DruidWebStatFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--druid访问监控界面 /druid/index.html-->
<servlet>
<servlet-name>DruidStatView</servlet-name>
<servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DruidStatView</servlet-name>
<url-pattern>/druid/*</url-pattern>
</servlet-mapping>
2)Tomcat中context.xml文件JNDI配置方式
com.alibaba.druid.pool.DruidDataSourceFactory实现了javax.naming.spi.ObjectFactory,可以作为JNDI数据源来配置
<TOMCAT_HOME>/conf/context.xml配置JNDI方式
<Resource
name="jdbc/MysqlDataSource"
factory="com.alibaba.druid.pool.DruidDataSourceFactory"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://192.168.1.233:3306/lead_oams?useUnicode=true&characterEncoding=utf-8"
username="lead_system"
password="password"
maxActive="50"
maxWait="10000"
removeabandoned="true"
removeabandonedtimeout="60"
logabandoned="false"
filters="stat"/>
(2)、Tomcat Jdbc Pool连接池
Maven依赖
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
<version>7.0.75</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-juli</artifactId>
<version>7.0.75</version>
</dependency>
1)Spring集成Tomcat Jbdc Pool配置方式
<!--tomcat jdbc pool数据源配置-->
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close">
<property name="poolProperties">
<bean class="org.apache.tomcat.jdbc.pool.PoolProperties">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/yi_piaodb?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="jmxEnabled" value="true"/>
<property name="testWhileIdle" value="true"/>
<property name="testOnBorrow" value="true"/>
<property name="testOnReturn" value="false"/>
<property name="validationInterval" value="30000"/>
<property name="validationQuery" value="SELECT 1"/>
<property name="timeBetweenEvictionRunsMillis" value="30000"/>
<property name="maxActive" value="100"/>
<property name="initialSize" value="10"/>
<property name="maxWait" value="10000"/>
<property name="minEvictableIdleTimeMillis" value="30000"/>
<property name="minIdle" value="10"/>
<property name="logAbandoned" value="false"/>
<property name="removeAbandoned" value="true"/>
<property name="removeAbandonedTimeout" value="60"/>
<property name="jdbcInterceptors" value="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"/>
</bean>
</property>
</bean>
2)Tomcat中context.xml文件JNDI配置方式
<Resource
name="jdbc/test"
auth="Container"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
testWhileIdle="true"
testOnBorrow="true"
testOnReturn="false"
validationQuery="SELECT 1"
validationInterval="30000"
timeBetweenEvictionRunsMillis="30000"
driverClassName="com.mysql.jdbc.Driver"
maxActive="100"
maxIdle="40"
maxWait="12000"
initialSize="10"
removeAbandonedTimeout="60"
removeAbandoned="true"
logAbandoned="true"
minEvictableIdleTimeMillis="30000"
jmxEnabled="true"
jdbcInterceptors=
"org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"
username="root"
password="root"
type="javax.sql.DataSource"
url="jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8"/>
Java代码中获取JNDI数据源
//1、初始化名称查找上下文
Context ctx =new InitialContext();
//2、通过JNDI名称找到DataSource
DataSource ds= (DataSource) ctx.lookup("java:comp/env/jdbc/test");
//3、通过ds获取数据库连接对象
Connectionconn = ds.getConnection();
The end!