前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >分享 Druid 连接池参数优化实战

分享 Druid 连接池参数优化实战

作者头像
猿芯
发布2020-09-18 15:30:50
11.4K6
发布2020-09-18 15:30:50
举报

前言

最近利用 MHA 做好 Mysql 读写分离后,时不时有用户反馈后台发布文章时,报程序“通用异常",经问题排查,里面涉及应用JDBC连接池参数及Mysql参数调整问题。

问题回顾

异常日志描述:

从异常信息反映来看,问题关键有两点

  1. 数据库连接池超时设置大于wait_timeout
  2. 日志提示,可以通过验证数据库连接或者设置: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毫秒

代码语言:javascript
复制
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(不限制物理连接时间),从创建连接开始计算,如果超过该时间,则会被清理。
代码语言:javascript
复制
druidDataSource.setPhyTimeoutMillis(15000)

参考例子

目前项目中趋于稳定的数据库连接池参数优化实战,Druid 代码如下:

代码语言:javascript
复制

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();
            }
        }
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-09-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构荟萃 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题回顾
  • 问题定位
  • 解决办法
  • 参考例子
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档