timeBetweenEvictionRunsMillis=60000 表示每隔60s运行一次连接回收器inEvictableIdleTimeMillis=300000 表示连接空闲时间超过300s回收连接
testOnBorrow=false 表示从连接池取出连接时,不执行检验,提高性能
validationQuery=SELECT 1 验证连接是否可用
testOnReturn=false 表示归还连接时,不进行检验
test-while-idle: true : 如果为true(默认true),当应用向连接池申请连接,并且testOnBorrow为false时,连接池将会判断连接是否处于空闲状态,如果是,则验证这条连接是否可用。
===============
testWhileIdle何时会起作用?
1)获取连接时;
2)testOnBorrow==false;
3)testWhileIdle==true;
使用代码在DruidDataSource的getConnectionDirect方法
注意:此时判断连接空闲的依据是空闲时间大于timeBetweenEvictionRunsMillis(默认1分钟),并不是使用minEvictableIdleTimeMillis跟maxEvictableIdleTimeMillis,也就是说如果连接空闲时间超过一分钟就测试一下连接的有效性,但并不是直接剔除;而如果空闲时间超过了minEvictableIdleTimeMillis则会直接剔除。
testWhileIdle的作用跟testOnBorrow是差不多的,都是在获取连接的时候测试连接的有效性,如果两者都为true,则testOnBorrow优先级高,则不会使用到testWhileIdle。
==================================
testOnBorrow:如果为true(默认false),当应用向连接池申请连接时,连接池会判断这条连接是否是可用的。
连接池是如何判断连接是否有效的?
如果是常用的数据库,则使用${DBNAME}ValidConnectionChecker进行判断,比如Mysql数据库,使用MySqlValidConnectionChecker的isValidConnection进行判断;
如果是其他数据库,则使用validationQuery判断;
验证不通过则会直接关闭该连接,并重新从连接池获取下一条连接;
testOnBorrow能够确保我们每次都能获取到可用的连接,但如果设置成true,则每次获取连接的时候都要到数据库验证连接有效性,这在高并发的时候会造成性能下降,可以将testOnBorrow设成false,testWhileIdle设置成true这样能获得比较好的性能。
======================
validationQuery:Druid用来测试连接是否可用的SQL语句,默认值每种数据库都不相同:
Mysql:SELECT 1;
SQLSERVER:SELECT 1;
ORACLE:SELECT 'x' FROM DUAL;
PostGresql:SELECT 'x';
validationQuery什么时候会起作用?
当Druid遇到testWhileIdle,testOnBorrow,testOnReturn时,就会验证连接的有效性,验证规则如下:
如果有相关数据库的ValidConnectionChecker,则使用ValidConnectionChecker验证(Druid提供常用数据库的ValidConnectionChecker,包括MSSQLValidConnectionChecker,MySqlValidConnectionChecker,OracleValidConnectionChecker,PGValidConnectionChecker);
如果没有ValidConnectionChecker,则直接使用validationQuery验证;
ValidConnectionChecker是如何验证的?
MySqlValidConnectionChecker会使用Mysql独有的ping方式进行验证,其他数据库其实也都是使用validationQuery进行验证
不同数据库的默认值不同;
如果是Mysql数据库,则validationQuery不会起作用,Mysql会使用ping的方式验证;
================
<!-- 数据源1 -->
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://192.168.0.109:3306/test?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<!--maxActive: 最大连接数量-->
<property name="maxActive" value="150"/>
<!--minIdle: 最小空闲连接-->
<property name="minIdle" value="5"/>
<!--maxIdle: 最大空闲连接-->
<property name="maxIdle" value="20"/>
<!--initialSize: 初始化连接-->
<property name="initialSize" value="30"/>
<!-- 连接被泄露时是否打印 -->
<property name="logAbandoned" value="true"/>
<!--removeAbandoned: 是否自动回收超时连接-->
<property name="removeAbandoned" value="true"/>
<!--removeAbandonedTimeout: 超时时间(以秒数为单位)-->
<property name="removeAbandonedTimeout" value="10"/>
<!--maxWait: 超时等待时间以毫秒为单位 1000等于60秒-->
<property name="maxWait" value="1000"/>
<!-- 在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位. -->
<property name="timeBetweenEvictionRunsMillis" value="10000"/>
<!-- 在每次空闲连接回收器线程(如果有)运行时检查的连接数量 -->
<property name="numTestsPerEvictionRun" value="10"/>
<!-- 1000 * 60 * 30 连接在池中保持空闲而不被空闲连接回收器线程-->
<property name="minEvictableIdleTimeMillis" value="10000"/>
<property name="validationQuery" value="SELECT NOW() FROM DUAL"/>
</bean>
==========================
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
<property name="maxActive" value="100"/>
<property name="maxIdle" value="30"/>
<property name="maxWait" value="1000"/>
<property name="defaultAutoCommit" value="true"/>
<property name="validationQuery" value="select * from dual"/>
</bean>
`===================
关闭PSCache.
<property name="poolPreparedStatements" value="false" />
<property name="maxPoolPreparedStatementPerConnectionSize"
value="-1" />
===========
SchedulerFactoryBean.setWaitForJobsToCompleteOnShutdown(true);
===========================
为了确保Druid的清理线程按照我们期望的执行清理逻辑,我们需要做到,
明确我们业务连接的数据库对空闲链接的保留时长上限(例如这个场景的MySQL的wait_time参数)
配置timeBetweenEvictionRunsMillis、minEvictableIdleTimeMillis和maxEvictableIdleTimeMillis时需要保证在两个清理周期之内超时(空闲时长>数据库wait_time)链接一定会被清理掉
保证maxEvictableIdleTimeMillis-minEvictableIdleTimeMillis>timeBetweenEvictionRunsMillis
也可通过设置phyTimeoutMillis参数规避Druid池中存在数据库侧已主动关闭的无效链接的情况
01-18
1579