Tomcat自带连接池tomcat-dbcp的优化

1,223 阅读6分钟

数据库连接池有时候获取连接特别慢;故参考了一些资料和官方文档,整理了一下使用Tomcat+JNDI的方式配置默认连接池的一些注意事项。

1、Tomcat的context.xml参考配置

<?xml version="1.0" encoding="UTF-8"?>
<Context path="/">
   <Resource  
    name="jdbc/TestDB" 
    type="javax.sql.DataSource"  
    factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"  
    driverClassName="com.mysql.jdbc.Driver" 
    url="jdbc:mysql://localhost:3306/test?"   
    username="xxx"   
    password="xxx"   
       
    maxWait="3000"   
    initialSize="10"    
    maxIdle="60"     
    minIdle="10"     
    maxActive="80"   
       
    validationQuery = "SELECT 1"
    testWhileIdle = "true"
    testOnBorrow = "false"
    timeBetweenEvictionRunsMillis = "30000" 
    minEvictableIdleTimeMillis = "1800000" 
    numTestsPerEvictionRun="10" 
    
    removeAbandoned="true"
    removeAbandonedTimeout="180"   
    />  
</Context>

2、参数说明

参数参考值描述
maxWait3000从池中取连接的最大等待时间,单位ms.
initialSize10初始化连接
maxIdle60最大空闲连接
minIdle10最小空闲连接
maxActive80最大活动连接
testWhileIdletrue指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除
testOnBorrowfalse借出连接时不要测试,否则很影响性能
validationQueryselect 1 from dual验证使用的SQL语句
timeBetweenEvictionRunsMillis30000每30秒运行一次空闲连接回收器
minEvictableIdleTimeMillis1800000池中的连接空闲30分钟后被回收
numTestsPerEvictionRun3在每次空闲连接回收器线程(如果有)运行时检查的连接数量
removeAbandonedtrue连接泄漏回收参数,当可用连接数少于3个时才执行
removeAbandonedTimeout180连接泄漏回收参数,180秒,泄露的连接可以被删除的超时值

3、部分参数详解

(1)配置timeBetweenEvictionRunsMillis = "30000"后,每30秒运行一次空闲连接回收器(独立线程)。并每次检查3个连接,如果连接空闲时间超过30分钟就销毁。销毁连接后,连接数量就少了,如果小于minIdle数量,就新建连接,维护数量不少于minIdle,过行了新老更替。

(2) testWhileIdle = "true" 表示每30秒,取出3条连接,使用validationQuery = "SELECT 1" 中的SQL进行测试 ,测试不成功就销毁连接。销毁连接后,连接数量就少了,如果小于minIdle数量,就新建连接。

(3) testOnBorrow = "false" 一定要配置,因为它的默认值是true。false表示每次从连接池中取出连接时,不需要执行validationQuery = "SELECT 1" 中的SQL进行测试。若配置为true,对性能有非常大的影响,性能会下降7-10倍。所在一定要配置为false.

(4)每30秒,取出numTestsPerEvictionRun条连接(默认值为3),发出"SELECT 1" SQL语句进行测试 ,测试过的连接不算是“被使用”了,还算是空闲的。连接空闲30分钟后会被销毁。

4、注意事项

(1) maxIdle值与maxActive值应配置的接近。因为,当连接数超过maxIdle值后,刚刚使用完的连接(刚刚空闲下来)会立即被销毁。而不是我想要的空闲M秒后再销毁起一个缓冲作用。这一点DBCP做的可能与你想像的不一样。

(2)若maxIdle与maxActive相差较大,在高负载的系统中会导致频繁的创建、销毁连接,连接数在maxIdle与maxActive间快速频繁波动,这不是我想要的。

(3)高负载系统的maxIdle值可以设置为与maxActive相同或设置为-1(-1表示不限制),让连接数量在minIdle与maxIdle间缓冲慢速波动。

(5)initialSize="5",会在tomcat一启动时,创建5条连接,效果很理想。 但同时我们还配置了minIdle="10",也就是说,最少要保持10条连接,那现在只有5条连接,哪什么时候再创建少的5条连接呢?

  • 等业务压力上来了, DBCP就会创建新的连接。
  • 通过配置timeBetweenEvictionRunsMillis=“时间”,DBCP会启用独立的工作线程定时检查,补上少的5条连接。销毁多余的连接也是同理。

5、连接销毁的逻辑

DBCP的连接数会在 0 - minIdle - maxIdle - maxActive 之间变化。变化的逻辑描述如下:

第一种情况

1、默认未配置initialSize(默认值是0)和timeBetweenEvictionRunsMillis参数时,刚启动tomcat时,连接数是0。当应用有一个并发访问数据库时DBCP创建一个连接。

2、目前连接数量还未达到minIdle,但DBCP也不自动创建新连接已使数量达到minIdle数量(没有一个独立的工作线程来检查和创建)。

3、随着应用并发访问数据库的增多,连接数也增多,但都与minIdle值无关,很快minIdle被超越,minIdle值一点用都没有。

4、直到连接的数量达到maxIdle值,这时的连接都是只增不减的。 再继续发展,连接数再增多并超过maxIdle时,使用完的连接(刚刚空闲下来的)会立即关闭,总体连接的数量稳定在maxIdle但不会超过maxIdle。

5、但活动连接(在使用中的连接)可能数量上瞬间超过maxIdle,但永远不会超过maxActive。

6、这时如果应用业务压力小了,访问数据库的并发少了,连接数也不会减少(没有一个独立的线程来检查和销毁),将保持在maxIdle的数量。

第二种情况

1、默认未配置initialSize(默认值是0),但配置了timeBetweenEvictionRunsMillis=“30000”(30秒)参数时,刚启动tomcat时,连接数是0。马上应用有一个并发访问数据库时DBCP创建一个连接。

2、目前连接数量还未达到minIdle,每30秒DBCP的工作线程检查连接数是否少于minIdle数量,若少于就创建新连接直到达到minIdle数量。

3、随着应用并发访问数据库的增多,连接数也增多,直到达到maxIdle值。这期间每30秒DBCP的工作线程检查连接是否空闲了30分钟,若是就销毁。但此时是业务的高峰期,是不会有长达30分钟的空闲连接的,工作线程查了也是白查,但它在工作。到这里连接数量一直是呈现增长的趋势。

4、当连接数再增多超过maxIdle时,使用完的连接(刚刚空闲下来)会立即关闭,总体连接的数量稳定在maxIdle。停止了增长的趋势。但活动连接(在使用中的连接)可能数量上瞬间超过maxIdle,但永远不会超过maxActive。

5、这时如果应用业务压力小了,访问数据库的并发少了,每30秒DBCP的工作线程检查连接(默认每次查3条)是否空闲达到30分钟(这是默认值),若连接空闲达到30分钟,就销毁连接。这时连接数减少了,呈下降趋势,将从maxIdle走向minIdle。当小于minIdle值时,则DBCP创建新连接已使数量稳定在minIdle,并进行着新老更替。

第三种情况

配置initialSize=“10”时,tomcat一启动就创建10条连接。其它同上。

注意事项

1、minIdle要与timeBetweenEvictionRunsMillis配合使用才有用,单独使用minIdle不会起作用。

2、removeAbandonedOnMaintenance只有在timeBetweenEvictionRunsMillis设置为正数的情况下才有效。

3、removeAbandonedTimeout属性是设置数据库连接被释最多空闲时间多少秒之后设置为空闲。默认移除废弃连接的时间为300秒。

4、如果启用removeAbandonedOnMaintenance 或 removeAbandonedOnBorrow,那些被认为废弃的连接对象有可能被池回收。这个机制以下情况下会触发:当getNumIdle() < 2并且getNumActive() > getMaxTotal() - 3及removeAbandonedOnBorrow 设置为true时;或当removeAbandonedOnMaintenance设置为true并且回收完成时。

参考资料:关于tomcat自带连接池dbcp的优化设置