Druid 数据库连接池高并发时大量线程等待 TIMED_WAITING 问题处理
druid数据库连接池 application.yml 最大连接池数量max-active 最大等待时间max-wait 高并发时大量线程等待TIMED_WAITING。
一、问题
在日常开发中,我们经常面临压力测试。这时会发现程序在一定并发数量下突然卡住。此时需要进行排查。
1.获取现场故障信息
jstack 6688
参数为PID,这时我们看堆栈信息,发现没有自己程序相关的类,但发现下面这样的句子:
"Druid-ConnectionPool-Create-418179060" #25 daemon prio=5 os_prio=0 tid=0x00007fa74d8ad000 nid=0x15a84 waiting on condition [0x00007fa6f8a30000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000c47d0990> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2480)
哦,原来是Druid在等待导致线程卡住,那怎么办呢?
2.根据打印信息检索解决方案
开始使用必应检索了一下,发现这篇讨论:线程卡死在druiddatasource上
3.根据检索到的信息做出尝试
既然讨论中提到可能和版本有关就检查了自己使用的版本,发现版本很新,出问题的可能很小。那么就调大最大活跃数进行试验,默认max-active为20,我们调为 100, 发现在调大最大活跃数之后,使用top命令查询,果然,cpu不再占用率很低,cpu开始开心地跑起来了。通过了这个并发数量的压力测试。
二、配置
spring:
datasource:
druid:
initial-size: 5 #初始化时建立物理连接的个数
min-idle: 5 #最小连接池数量
max-active: 100 #最大连接池数量,like12 find bug,此值设得太小(如20) 高并发时会导致大量请求因等待连接池连接超时而处理失败(max-wait调小时) 推荐设置: 普通20 高并发100 最大200
max-wait: 5000 #获取连接时最大等待时间,单位毫秒,like12 find bug,此值不能设得太大(如60000),高并发时会导致系统卡死(大量线程一直挂起等待) 推荐设置: 普通60000 高并发5000
time-between-eviction-runs-millis: 60000 #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
min-evictable-idle-time-millis: 300000 #配置一个连接在池中最小生存的时间,单位是毫秒
#Oracle模式
#validation-query: SELECT 1 FROM DUAL #用来检测连接是否有效的sql
#MySQL模式
validation-queryM: SELECT 1 #用来检测连接是否有效的sql
test-while-idle: true #申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效
test-on-borrow: false #申请连接时执行validationQuery检测连接是否有效,如果为true会降低性能
test-on-return: false #归还连接时执行validationQuery检测连接是否有效,如果为true会降低性能
pool-prepared-statements: true #打开PSCache,并且指定每个连接上PSCache的大小
max-pool-prepared-statement-per-connection-size: 20 #要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
#like12 modified,jpa拦截dbms_random wall会拦截dbms_random,使得无法随机排序
#filters: stat,wall,slf4j #配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,slf4j #配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
#通过connectProperties属性来打开mergeSql功能;慢SQL记录
connection-properties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
#配置DruidStatFilter,用于采集web-jdbc关联监控的数据
web-stat-filter:
enabled: true
url-pattern: "/*"
#排除一些不必要的url过滤
exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
#配置DruidStatViewServlet
stat-view-servlet:
url-pattern: "/druid/*"
#IP白名单(没有配置或者为空,则允许所有访问)
#allow: 127.0.0.1,192.168.1.106
#IP黑名单(存在共同时,deny优先于allow)
#deny: 192.168.1.73
#禁用HTML页面上的“Reset All”功能
reset-enable: fasle
#可视化界面,登录名
login-username: ***
#可视化界面,登录密码
login-password: ***
另外的参考:
以下为经过压测验证后的我们服务的配置,供参考:
// 初始连接数
dataSource.setInitialSize(10);
// 最小连接池数量
dataSource.setMinIdle(10);
// 最大连接池数量
dataSource.setMaxActive(100);
// 配置获取连接等待超时时间 毫秒
dataSource.setMaxWait(100);
//缓存通过以下两个方法发起的SQL:
dataSource.setPoolPreparedStatements(true);
//每个连接最多缓存多少个SQL
dataSource.setMaxPoolPreparedStatementPerConnectionSize(50);
//检查空闲连接的频率,单位毫秒, 非正整数时表示不进行检查
dataSource.setTimeBetweenEvictionRunsMillis(-1);
//池中某个连接的空闲时长达到 N 毫秒后, 连接池在下次检查空闲连接时,将回收该连接,要小于防火墙超时设置
dataSource.setMinEvictableIdleTimeMillis(300000);
//当程序请求连接,池在分配连接时,是否先检查该连接是否有效。(高效)
dataSource.setTestWhileIdle(true);
// 程序 申请 连接时,进行连接有效性检查(低效,影响性能)
dataSource.setTestOnBorrow(false);
//程序 返还 连接时,进行连接有效性检查(低效,影响性能)
dataSource.setTestOnReturn(false);
// 要求程序从池中get到连接后, N 秒后必须close,否则druid 会强制回收该连接,不管该连接中是活动还是空闲, 以防止进程不会进行close而霸占连接。
dataSource.setRemoveAbandoned(true);
// 设置druid 强制回收连接的时限,当程序从池中get到连接开始算起,超过此值后,druid将强制回收该连接,单位秒。
// 结合业务来看,存在jpa极大事务;不好设置 暂时为设置两分钟
dataSource.setRemoveAbandonedTimeout(120);
//当druid强制回收连接后,是否将stack trace 记录到日志中
dataSource.setLogAbandoned(true);
相关文章:
druid数据库连接池 application.yml 最大连接池数量max-active 最大等待时间max-wait 高并发时大量线程等待TIMED_WAITING
踩坑DruidDataSource导致的服务卡死
为者常成,行者常至
自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)