问题:

我们线上配置的具体配置 minIdle=20,详情见附件1

druid日志打印出来 activeCount+poolingCount=4 具体日志见附件2.

连接池的总量已经低于最小值了。

出现这种原因:

业务从连接池获取连接后,testWhileIdle,发现连接失败(注:超过服务端空闲时间,已经被数据库服务端强行关闭,目前我们的运维体系里,服务端关闭被强行定义为15分钟)此时抛弃该连接,数量从初始值的20变为19.后面反复会陆续降低到业务真正使用的连接数,我们的业务上是4个。

进一步分析:

对于震荡式业务, 如果业务对连接数需求新增,会新建连接,连接池数量从4个增加到6个(在我们的业务场景下),然后业务需求降低,会有几个连接一直不被使用(连接池数据结构使用的数组堆栈),最终等到业务震荡高峰时被获取,如果刚好超过了minEvictableIdleTimeMillis并且已经被服务端关闭,testWhileIdle后被丢弃。

这个会导致连接池的意义被降低了,极端情况,对震荡式的业务会导致获取连接时会遇到 1.先testWhileIdle 2.再await等待CreateConnectionThread线程新建连接

代码分析和个人想法:

目前的CreateConnectionThread线程用于新建扩充,DestroyConnectionThread用于收缩:

看了源代码,我们是用的1.0.8 http://grepcode.com/file/repo1.maven.org/maven2/com.alibaba/druid/1.0.8/com/alibaba/druid/pool/DruidDataSource.java#DruidDataSource.shrink%28boolean%29

1. CreateConnectionThread 里面有这段代码

// 必须存在线程等待,才创建连接

if (poolingCount >= notEmptyWaitThreadCount) {

empty.await();

}

个人看法: 限制会不会太强了,虽然看上去较合理,但无法从4补全到20(minIdle配置值)的数量,失去了人工配置的minIdle意义,也无法很好的处理上面描述震荡式的的业务场景。

2. DestroyConnectionThread 里面shrink代码

final int checkCount = poolingCount - minIdle;

final long currentTimeMillis = System.currentTimeMillis();

for (int i = 0; i < checkCount; ++i) {

//闲置时间判断 和连接缩减

}

这里只对大于minIdle的连接进行缩减。

个人看法:是不是缺乏了对所有连接的test检查。场景:连接池配置超时时间是4个小时,mysql配置的是2个小时。目前代码会导致一些连接被服务端中断了,但是没有被有效关闭回收。

附件1:

jdbc.driver=com.mysql.jdbc.Driver

jdbc.initialPoolSize=20

jdbc.minPoolSize=20

jdbc.maxPoolSize=50

jdbc.maxWaitTime=6000

jdbc.maxIdleTime=14400000

jdbc.acquireIncrement=5

jdbc.acquireCheckoutTimeout=3000

jdbc.idleConnectionTestPeriod=1800

mysql.driver.slave=com.mysql.jdbc.Driver

class="com.alibaba.druid.pool.DruidDataSource"init-method="init"

destroy-method="close">

value="20"/>

value="druid.stat.logSlowSql=true;druid.stat.slowSqlMillis=500;druid.stat.mergeSql=true"/>

附件2:

druid监控日志如下,{   "url": "jdbc:mysql:///dababase?characterEncoding=UTF-8",

"dbType": "mysql",

"name": "DataSource-4129454",

"activeCount": 0,

"activePeak": 4,

"activePeakTime": "2016-02-15 22:00:10",

"poolingCount": 4,

"poolingPeak": 4,

"poolingPeakTime": "2016-02-15 21:59:13",

"connectCount": 9354,

"closeCount": 9354,

"executeCount": 9962,

"errorCount": 1,

"commitCount": 305,

"pstmtCacheHitCount": 9956,

"pstmtCacheMissCount": 6,

"startTransactionCount": 305,

"transactionHistogram": [

0,

305

],

"connectionHoldTimeHistogram": [

8999,

353,

2

]

}

这个是druid打印的log日志

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐