共计 1685 个字符,预计需要花费 5 分钟才能阅读完成。
@[toc]
景象
目前营销数据库应用的是阿里云 MYSQL 数据库,近期须要反对 DBA 对阿里云 RDS 进行降级,降级布告如下:
凌晨 5 点 10 分进行降级后开始日志报错,错误信息如下:
问题剖析与论断
个别呈现 duridCommunicationsException 起因是因为连接池获取曾经生效的连贯导致。从 mysql 上来说:
Mysql 服务器默认的“wait_timeout”是 8 小时 (也就是默认的值默认是 28800 秒),即一个 connection 闲暇超过 8 个小时,Mysql 将主动断开该 connection,艰深的讲就是一个连贯在 8 小时内没有流动,就会主动断开该连贯。而连接池却认为该连贯还是无效的 (因为并未校验连贯的有效性),当利用申请应用该连贯时,就会导致下面的报错。
从 druid 配置属性上和连贯生效的属性有以下几个:
- minEvictableIdleTimeMillis:连贯闲暇工夫大于该值并且池中闲暇连贯大于 minIdle 则敞开该连贯。配置中采纳的默认值 30 分钟。
- maxEvictableIdleTimeMillis:连贯闲暇工夫大于该值,不论 minIdle 都敞开该连贯。配置中采纳的默认值 7 个小时。
- maxidle:目前 druid 曾经废除了 maxidle 属性,应用 maxActive 和 minIdel 来代替,参考 https: //github.com/alibaba/druid/wiki/FAQ,从 druid 配置上看,minIdle 是 50,maxActive 是 400(代码上设置不合理,可调整)。
即实践上 druid 默认连贯生效的最大 7 个小时也小于数据库 8 个小时,不会存在配置层面上获取到生效的连贯。再从布告上看,有阐明:“在迁徙过程中会有 30 秒的连贯闪断”,阐明 rds 闪断后原有的的数据库连贯 都曾经生效了,而 smc 零碎中 druid 连接池还放弃着无效状态,所以会导致 com.mysql.jdbc.exceptions.jdbc4. CommunicationsException 产生。
解决方案
间接思路时在 druid 线程拿到连贯后校验一下就 ok 了,波及到相干属性有 test- WhileIdle、testOnBorrow,意义如下:
- testWhileIdle:如果为 true(默认 true),当利用向连接池申请连贯,并且 testOnBorrow 为 false 时,连接池将会判断连贯是否处于闲暇状态,如果是,则验证这条连贯是否可用 (高效,举荐应用)。
- testOnBorrow:(默认 false) 申请连贯时进行连贯有效性查看 (低效,影响性能),与 testWhileIdle 是差不多的,都是在获取连贯的时候测试连贯的有效性,如果两者都为 true,则 testOnBorrow 优先 级高,则不会应用到 testWhileIdle。
- validationQuery:在连接池返回连贯给调用者前用来对连贯进行验证的查问 SQL,要求为一条查问语句 (开启 testWhileIdle 必须要设置 validationQuery)。
druid 配置中减少:
spring.datasource.druid.test-on-borrow=false
spring.datasource.druid.test-while-idle=true
spring.datasource.druid.validation-query=SELECT 1
此时还有一个疑难,在没有配置上述属性的状况下,testWhileIdlel 默认为 true,testOnBorrow 默认 为 false,validationQuery 默认为空,为什么没有强制设置 validationQuery 呢? 此时要分 2 个阶段阐明问题:
- durid 初始化阶段:只打了 error,并未中断初始化过程
- 获取连贯过程:校验了 minEvictableIdleTimeMillis 和 maxEvictableIdleTimeMillis,发现 validation- Query 为 null 间接返回了,所以上述配置只须要减少 validationQuery 的配置也能解决问题。
欢送关注微信公众号:方辰的博客