分享 Druid 连接池参数优化实战
前言
最近利用 MHA
做好 Mysql
读写分离后,时不时有用户反馈后台发布文章时,报程序“通用异常",经问题排查,里面涉及应用JDBC
连接池参数及Mysql
参数调整问题。
问题回顾
异常日志描述:
从异常信息反映来看,问题关键有两点
- 数据库连接池超时设置大于
wait_timeout
- 日志提示,可以通过验证数据库连接或者设置:
autoReconnect=true
来避免此异常
从以上两点可以推测
- 第一、应用程序数据库连接池超时参数设置有问题
- 第二、安装
Mysql
数据库时,对于Mysql
的内在参数wait_timeout
没有做实际场景的优化处理
问题定位
wait_timeout
参数说明:
wait_timeout
具体含义是服务器关闭非交互连接之前等待活动秒数。MySQL
缺省配置情况下,wait_timeout
的初始值是28800
秒,也就是8
小时。如果wait_timeout
超时时间设置过大,在MySQL
管理系统里会产生大量的SLEEP
进程无法及时释放,会导致服务器系统性能下降;同时该参数设置过小,会导致Mysql
处理某些事务未处理,连接不可用状态。
也就是说如果在wait_timeout
设置期间内,数据库连接Connection
一直处于空闲等待状态,mysql
内部会自动关闭此连接,而应用程序无法感知到,依然认为连接池合法持有该连接。当应用端再次用该连接来进行数据库操作时,就产生上述异常错误。
应用端Druid
数据库连接池参数设置代码如下:
发现连接池有个MaxWait
参数设置过大:60000
毫秒
druidDataSource.setMaxWait(60000)
然后在CSDN
上,发现有个同行碰到同样的问题:
发现数据库等待超时时间(
wait_timeout
)是28800
,也就是8
小时,而应用程连接池参数max-wait: 30000
,所以导致项目判定该链接可用,而mysql
判定该连接不可用导致连接失败。
解决办法
根据上面的分析思路,我们排查了Mysql
生产库,发现默认Mysql
超时时间(wait_timeout
)也是28800
,但是应用层连接池MaxWait
参数设置成60000
,于是我把MaxWait
参数设置成10000
,小于Mysql
超时时间(wait_timeout
):28800
,在测试环境等待8
小时后,报错消失了。
其他扩展思路(来源网络):
- 思路一:在
jdbc-url
后添加&autoReconnect=true
,使用后无效,查的该方案只适用于Mysql4
之前的版本有效 - 思路二:将
mysql
回收空闲连接的时间变长,mysql
默认回收时间是8
小时,可以在mysql
目录下的my.ini
中增加下面配置,将时间改为1
天。单位是秒,最大好像是24
天。此配置会拖累数据库性能,弃用该方案。 - 思路三:配置
druid
链接池,使用validation-query test-on-borrow: true test-while-idle: true
三种属性,每次获取数据库连接时判断该连接是否可用。同时设置druidDataSource.setPhyTimeoutMillis
参数:连接最大存活时间,默认是-1
(不限制物理连接时间),从创建连接开始计算,如果超过该时间,则会被清理。
druidDataSource.setPhyTimeoutMillis(15000)
参考例子
目前项目中趋于稳定的数据库连接池参数优化实战,Druid 代码如下:
private void configDruidParams(DruidDataSource druidDataSource) {
druidDataSource.setMaxActive(20);
druidDataSource.setInitialSize(1);
// 配置获取连接等待超时的时间
druidDataSource.setMaxWait(10000);
druidDataSource.setMinIdle(1);
// 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
druidDataSource.setTimeBetweenEvictionRunsMillis(60000);
// 配置一个连接在池中最小生存的时间,单位是毫秒 超过这个时间每次会回收默认3个连接
druidDataSource.setMinEvictableIdleTimeMillis(30000);
// 线上配置的mysql断开闲置连接时间为1小时,数据源配置回收时间为3分钟,以最后一次活跃时间开始算
druidDataSource.setMaxEvictableIdleTimeMillis(180000);
// 连接最大存活时间,默认是-1(不限制物理连接时间),从创建连接开始计算,如果超过该时间,则会被清理
druidDataSource.setPhyTimeoutMillis(15000);
druidDataSource.setValidationQuery("select 1");
druidDataSource.setTestWhileIdle(true);
druidDataSource.setTestOnBorrow(false);
druidDataSource.setTestOnReturn(false);
druidDataSource.setPoolPreparedStatements(true);
druidDataSource.setMaxOpenPreparedStatements(20);
druidDataSource.setUseGlobalDataSourceStat(true);
druidDataSource.setKeepAlive(true);
druidDataSource.setRemoveAbandoned(true);
druidDataSource.setRemoveAbandonedTimeout(180);
try {
druidDataSource.setFilters("stat,slf4j");
List filterList = new ArrayList<>();
filterList.add(wallFilter());
druidDataSource.setProxyFilters(filterList);
} catch (SQLException e) {
e.printStackTrace();
}
}
- [认证授权] 1.OAuth2授权
- 机器学习(四)——梯度下降算法解释以及求解
- 在Windows上运行单节点的Cassandra
- Mono技术规格
- 如何站在使用者的角度来设计SDK-微信公众号开发SDK(消息处理)设计之抛砖引玉
- 机器学习(三)——k-近邻算法基础
- 利用Windows性能计数器(PerformanceCounter)监控
- zepto 基础知识(1)
- [C#7] 1.Tuples(元组)
- 防止“rm-rf/”误删除的5种方法
- 基于DotNetOpenAuth实现OpenID 服务提供者
- .NET 和Java 对象 XML序列化 库WOX
- jquery mobile 移动web(6)
- IIS6 间歇性的发生500错误的解决方法
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Spring解决循环依赖的思路
- Spring中Bean的创建流程
- 详解RocketMQ事务消息
- 带你白嫖程序带宽限制命令Trickle
- Fix SSH客户端登录会话超时设置
- JAVA的泛型与反射的联合应用
- 专项测试实战 | 如何测试 App 流畅度(基于 FPS 和丢帧率)
- 计算上传文件的存放路径
- 按照list中实体类的某一属性排序
- java邮件开发
- java计算某日期之后的日期
- 文件上传之Html5 + jQuery上传、asp.net web api接收
- Struts2自定义结果视图(servlet验证码)
- jQuery Ajax传递数组到asp.net web api参数为空
- asp.net web api集成微信服务(使用Senparc微信SDK)