alibaba druid 在springboot start autoconfig下的bug

标签(空格分隔):druid springboot start autoconfig


  • 背景
  • 发现、分析过程
  • 总结

背景

最近在使用alibaba druid进行多数据源连接的时候无意中发现一个小bug,已经提交github issue 官方已经fix。issue 地址:https://github.com/alibaba/druid/issues/1796

发现、分析过程

我们使用的java开发框架是封装好的。框架对数据源的支持是master、slave架构的,就是可以一组多从数据源,内部会自动进行主从写入、查询切换。

我们现在处于.net专java过程中,特殊场景下新java系统需要连接两个数据源,默认连接mysql数据源,但是有时候还需要查询sqlserver数据源来获取一些兼容性数据。

所以,在配置第二个数据源的时候,系统load就报错。

我们使用springboot框架,datasource config 基于springboot properties进行配置。然后使用configuration 进行自动druid daasource bean的创建。这看起来好像没什么问题。

    @Bean(name = "dataSource")
@ConfigurationProperties(prefix = "ecommon.order.druid")
public DataSource getOrderDataSource() {
return new DruidDataSource();
}

如果不是springboot,一般都会自己来初始化所有的属性。从配置文件加载配置,然后手动设置DruidDataSource bean。

没多想,就直接用这种方式使用了。但是在启动的时候,初始化bean的时候就报错了。

'maxEvictableIdleTimeMillis' threw exception; nested exception is java.lang.IllegalArgumentException: maxEvictableIdleTimeMillis must be grater than minEvictableIdleTimeMillis

大概意思是说,'maxEvictableIdleTimeMillis'最大存活时间必须大于'minEvictableIdleTimeMillis'最小存活时间。

第一反应肯定是配置错了,检查配置。

##一个连接在池中最小生存的时间(ms)
ecommon.order.druid.minEvictableIdleTimeMillis=300000
##一个连接在池中最大生存的时间(ms)
ecommon.order.druid.maxEvictableIdleTimeMillis=600000

好像没错啊,然后在debug下,问题同样出现。minEvictableIdleTimeMillis属性和maxEvictableIdleTimeMillis属性的前后顺序好像也没问题。试试看的心里,将两个属性前后顺序交换下,问题还是出现。

蒙蔽状态_

感觉这个问题有点诡异了,时间要紧,直接找到报错的地方,进行源码跟踪。

上 github search alibaba druid 首页,直接gith clone下来,定位到错误提示的位置。

全局查找的时候有两处有这个exception的throw。

一: init 方法

public void init() throws SQLException {
if (maxEvictableIdleTimeMillis < minEvictableIdleTimeMillis) {
throw new SQLException("maxEvictableIdleTimeMillis must be grater than minEvictableIdleTimeMillis");
}

为了便于阅读,我删掉了init中对我们分析问题来说无用的代码。

二:setMaxEvictableIdleTimeMillis 方法

    public void setMaxEvictableIdleTimeMillis(long maxEvictableIdleTimeMillis) {
if (maxEvictableIdleTimeMillis < 1000 * 30) {
LOG.error("maxEvictableIdleTimeMillis should be greater than 30000");
} if (maxEvictableIdleTimeMillis < minEvictableIdleTimeMillis) {
throw new IllegalArgumentException("maxEvictableIdleTimeMillis must be grater than minEvictableIdleTimeMillis");
} this.maxEvictableIdleTimeMillis = maxEvictableIdleTimeMillis;
}

这两个方法逻辑都比较简单,init初始化的时候会检查这两个bean属性的值。setMaxEvictableIdleTimeMillis,设置这个最大存活时间的时候有一个检查。如果你的最大存活时间小于最小存活时间直接报错。

所以直接在这两个地方打上断点,然后debug,在跟踪下变量的值基本就知道问题在哪里了。

通过debug,发现直接new DruidDataSource()使用数据源,不会走到init方法。不会进入到触发报错的地方。貌似我的代码路径应该不会产生这个检查。继续运行,看setMaxEvictableIdleTimeMillis方法什么情况。

发现问题了,在进行setMaxEvictableIdleTimeMillis方法的时候,minEvictableIdleTimeMillis属性的值是1800000。

看下这个值哪里来的。

protected volatile long  minEvictableIdleTimeMillis  = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
public static final long  DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS =
1000L * 60L * 30L;

minEvictableIdleTimeMillis 属性有一个default值。单位是ms(millisecond),所以这里的default 值是30m(minute)分钟。

我们配置的是600000ms,所以比1800000小。但是这个就奇怪了,我们明明设置了minEvictableIdleTimeMillis 参数。为什么没起作用,一下子就想到是不是顺序问题。

然后继续debug,先绕过这个检查,看是不是setMinEvictableIdleTimeMillis 方法在setMaxEvictableIdleTimeMillis 方法之后执行,导致这个检查和配置顺序冲突。

debug下来,确实是这个问题。然后就比较好奇,我们现在所使用的这个框架帮我们封装了druid的时候是怎么处理的,通过查看框架源码,里面有一个hashcode的排序,解决了这个问题。(果然老司机,高手)这里就不展开了。

那么我们如果解决这个问题,其实很简单,知道问题在哪里绕过去还是很简单的。

一:先把配置的minEvictableIdleTimeMillis、maxEvictableIdleTimeMillis获取进来

@Data
@EqualsAndHashCode
@ConfigurationProperties(prefix = "ecommon.order.druid")
public class SqlServerDruidConfig {
private Long minEvictableIdleTimeMillis;
private Long maxEvictableIdleTimeMillis;
}

二:然后自己先设置一下这两个属性,springboot autoconfig 的时候就不会出错

 @Autowired
private SqlServerDruidConfig druidConfig; @Bean(name = "dataSource")
@ConfigurationProperties(prefix = "ecommon.order.druid")
public DataSource getOrderDataSource() { DruidDataSource dataSource = new DruidDataSource(); /**setMinEvictableIdleTimeMillis需要先设置*/
dataSource.setMinEvictableIdleTimeMillis(druidConfig.getMinEvictableIdleTimeMillis());
dataSource.setMaxEvictableIdleTimeMillis(druidConfig.getMaxEvictableIdleTimeMillis()); return dataSource;
} @Bean
public SqlServerDruidConfig getDruidConfig() {
return new SqlServerDruidConfig();
}

问题到这里分析就结束了。这个小bug,alibaba druid 已经fix。

如果你对如何fix感兴趣,请参看druid 有关于autoconfiger修复的代码:

https://github.com/lihengming/druid/commit/ca13e8ff5a78c83f953fa8fb320c56be223219e1

总结

突然能明白,其实有关于开源的好处,你已经获益了。可以一起参与使用,一起参与发现问题,一起参与fixbug。这也许就是linux、git这类优秀艺术品背后的核心技术价值观。

github 地址:https://github.com/Plen-wang

alibaba druid 在springboot start autoconfig 下的bug的更多相关文章

  1. alibaba/druid 下的 密码加密

    使用ConfigFilter cliangch edited this page on 3 Feb · 12 revisions ConfigFilter的作用包括: 从配置文件中读取配置 从远程ht ...

  2. 【SpringBoot | Druid】SpringBoot整合Druid

    SpringBoot整合Druid Druid是个十分强大的后端管理工具,具体的功能和用途请问阿里爸爸 1. 在pom.xml中导入包 <!-- alibaba 的druid数据库连接池 --& ...

  3. com.alibaba.druid.pool.DruidDataSource : {dataSource-2} init error

    这几天准备写一个项目,其中的整合druid的时候,发现出现了下面这个错误.找了好久都没有找到.网上的各种解决方法都不对. 2018-11-07 16:26:28.940 INFO 19684 --- ...

  4. 解决ERROR - unregister mbean error javax.management.InstanceNotFoundException: com.alibaba.druid:type=

    https://blog.csdn.net/chengsi101/article/details/72627062 https://www.cnblogs.com/gradven/p/6323195. ...

  5. 转-Hive/Phoenix + Druid + JdbcTemplate 在 Spring Boot 下的整合

    Hive/Phoenix + Druid + JdbcTemplate 在 Spring Boot 下的整合 http://blog.csdn.net/balabalayi/article/detai ...

  6. Tomcat:javax.management.InstanceNotFoundException: com.alibaba.druid:type=DruidDataSourceStat异常

    问题: 在关闭tomcat时: Tomat报出一下异常:ERROR [com.alibaba.druid.stat.DruidDataSourceStatManager] – unregister m ...

  7. 淘宝druid报错:javax.management.InstanceNotFoundException: com.alibaba.druid:type=DruidDataSourceStat

    问题: 启动tomcat报错: Tomat报出一下异常:ERROR [com.alibaba.druid.stat.DruidDataSourceStatManager] – unregister m ...

  8. 解决若依linux启动ERROR - unregister mbean error javax.management.InstanceNotFoundException: com.alibaba.druid:type=

    项目中使用druid对数据库连接池进行管理,在本地及测试环境均无问题,但是上了生产环境后,每当tomcat第一次启动时,日志未报错,但是页面总是出不来,在关闭tomcat时,看日志,发现报错如下: E ...

  9. java.lang.IllegalStateException: Illegal access: this web application instance has been stopped already. Could not load [META-INF/services/com.alibaba.druid.filter.Filter].

    九月 11, 2019 2:56:36 下午 org.apache.catalina.loader.WebappClassLoaderBase checkStateForResourceLoading ...

随机推荐

  1. StringBuffer类的使用

    //简单记录下Java中StringBuffer类的基本功能使用public class Test01{ public static void main(String[] args){ //New一个 ...

  2. 第 15 章 可扩展性设计之 Cache 与 Search 的利用

    前言: 前面章节部分所分析的可扩展架构方案,基本上都是围绕在数据库自身来进行的,这样是否会使我们在寻求扩展性之路的思维受到“禁锢”,无法更为宽广的发散开来.这一章,我们就将跳出完全依靠数据库自身来改善 ...

  3. linux centos7.0安装subversion

    安装环境以及软件版本如下: subversion使用1.8.17版本,CentOS7.0(64位) 安装svn共需要使用如下软件,apr-1.5.2.tar.gz.apr-util-1.5.4.tar ...

  4. 测试class

    各种断言方法: assertEqual(a,b) a == b assertNotEqual(a,b) a != b assertTrue(x) x == True assertFalse(x) x ...

  5. Java编程之反射中的注解详解

    "注解"这个词,可谓是在Java编程中出镜率比较高,而且也是一个老生常谈的话题.我们之前在聊Spring相关的东西时,注解是无处不在,之前我们简单的聊过一些"注解&quo ...

  6. EIGRP负载均衡、手工汇总、泄露明细、安全认证

    基于6.6.6.6/24访问13.1.1.1/24进行负载均衡实例图 一.等价负载均衡 等价负载均衡前,R5路由器背后的6.6.6.6/24访问R1的13.1.1.1/24, 从15.1.1.0/24 ...

  7. Vulkan Tutorial 05 逻辑设备与队列

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 Introduction 在选择要使用的物理设备之后,我们需要设置一个逻辑设备用于交 ...

  8. VR问题无关方向,VR全景为您领航,全景智慧城市已势不可当

    2016年,VR绝对是互联网科技圈的一个高频词. 在这一年里,Magic Leap获得阿里领投的近8亿美元的融资,VR公司的商业价值得到认可.Oculus Rift和HTC Vive的VR产品正式发货 ...

  9. 初入计算机图形学(二):对bidirectional path tracing的一些困惑

    本人水平有限,若有错误也请指正~ 前文提及了光线追踪的一些常用手法,但是其中path tracing的实现最为简单,但是其最致命的一个缺点就是图像收敛速度很慢..原因在于从摄影机发射出的每一条光线若不 ...

  10. 新写的高仿Arcmap,要的拿去玩玩

    本想着对所学的ArcGIS Engine开发作一个了结,于是乎写了这么一个仿照Arcmap的程序.我所见过的地理信息系统中,ArcGIS是功能最完善.二次开发最易上手的平台了(当然别提AutoCAD那 ...