atomikos数据源连接超时和耗尽问题

1.问题描述

项目里之前用的是原生druid数据源,后来为了解决多个数据源的事务一致性问题,引入了atomikos数据源。
java配置如下

 @Bean(name = "bdpDatasource")
    public DataSource bdpDatasource() {
        DruidXADataSource druidXADataSource = new DruidXADataSource();
        druidXADataSource.setUrl(bdpProperties.getUrl());
        druidXADataSource.setPassword(bdpProperties.getPassword());
        druidXADataSource.setUsername(bdpProperties.getUsername());
        druidXADataSource.setConnectionProperties(bdpProperties.getConnectionProperties());
        druidXADataSource.setDriverClassName(bdpProperties.getDriverClassName());
        druidXADataSource.setMaxActive(bdpProperties.getMaxActive());
        druidXADataSource.setMaxWait(bdpProperties.getMaxWait());
        druidXADataSource.setMinIdle(bdpProperties.getMinIdle());
        druidXADataSource.setInitialSize(bdpProperties.getInitialSize());
        druidXADataSource.setValidationQuery(bdpProperties.getValidationQuery());
        druidXADataSource.setValidationQueryTimeout(bdpProperties.getValidationQueryTimeout());
        druidXADataSource.setTestOnBorrow(bdpProperties.getTestOnBorrow());
        druidXADataSource.setTestOnReturn(bdpProperties.getTestOnReturn());
        druidXADataSource.setTestWhileIdle(bdpProperties.getTestWhileIdle());
        druidXADataSource.setTimeBetweenEvictionRunsMillis(bdpProperties.getTimeBetweenEvictionRunsMillis());
        druidXADataSource.setMinEvictableIdleTimeMillis(bdpProperties.getMinEvictableIdleTimeMillis());
        try {
            druidXADataSource.setFilters(bdpProperties.getFilters());
        } catch (SQLException e) {
            e.printStackTrace();
        }
        AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
        xaDataSource.setXaDataSource(druidXADataSource);
        xaDataSource.setMaxPoolSize(bdpProperties.getMaxActive());
        xaDataSource.setMinPoolSize(bdpProperties.getMinIdle());
        xaDataSource.setMaxLifetime(bdpProperties.getMaxWait());
        xaDataSource.setTestQuery(bdpProperties.getValidationQuery());
        xaDataSource.setUniqueResourceName("bdpDatasource");
        return xaDataSource;
    }

properties配置如下

spring.datasource.druid.driverClassName=com.mysql.jdbc.Driver
spring.datasource.druid.maxActive=20
spring.datasource.druid.maxWait=20000
spring.datasource.druid.minIdle=5
spring.datasource.druid.initialSize=5
spring.datasource.druid.validationQuery=select 1
spring.datasource.druid.validationQueryTimeout=30000
spring.datasource.druid.testOnBorrow=true
spring.datasource.druid.testOnReturn=false
spring.datasource.druid.testWhileIdle=false
spring.datasource.druid.timeBetweenEvictionRunsMillis=60000
spring.datasource.druid.minEvictableIdleTimeMillis=300000
#spring.datasource.druid.max-evictable-idle-time-millis=900000
spring.datasource.druid.filters=stat,wall,slf4j,config

结果开发环境偶尔报如下错误
在这里插入图片描述
上线到生产环境后报如下错误
在这里插入图片描述

2.问题重现

开始看生产环境的报错,怀疑是数据库那边的问题,因为测试环境从没有报过生产环境这样的错误,所以排除代码原因。
后来同事说可能是测试和生产并发量不一样,因为生产的并发量多,而有个接口是隔20秒就会调一次的,于是造成连接耗尽。
于是开始使用jemter压测,测试的环境如下

- 现有atomikos数据源配置

1.使用jmeter模拟2000个并发调用任意一个接口,结果重现了生产环境的错误。
2.将数据源配置的maxActive参数改为100,再使用jmeter模拟2000个并发调用接口,结果没有任何问题

- 以前的druid数据源配置

maxActive改回20,再使用jmeter模拟2000个并发调用接口,结果没有任何问题

3.分析推测

看来是连接数太小,导致atomikos连接耗尽。
但是之前咱们用的是原生druid数据源,maxActive配置也只有20,为什么没有耗尽呢?
查看druid的数据源监控界面发现,在maxActive相同的前提下————
在这里插入图片描述
当使用原生druid时:活跃连接数在并发操作结束后,很快恢复到最小连接数左右
当使用atomikos时:活跃连接数在并发操作结束后,需要等一段时间才能恢复到最小连接数左右

4.结论

DruidXADataSource的连接归还速度远小于原生druid,导致并发量大的情况下,由于本来占用连接就多,归还速度又慢,最终出现上述问题。

5.解决

调大maxActive为100

6.参考资料

https://blog.csdn.net/taxuexunmei414923794/article/details/14450181

7.后续方案

后来发现这种方式不够彻底,因为当并发量继续增加时,maxActive参数不得不继续调大,否则还是可能出现上述问题。
最终解决是将DruidXADataSource 换成MysqXADataSource ,在maxActive依旧是20的情况下,经过压力测试,发现问题得以彻底解决。

@Bean(name = "bdpDatasource")
    public DataSource bdpDatasource() {
        MysqlXADataSource mysqlXADataSource = new MysqlXADataSource();
        mysqlXADataSource.setUrl(bdpProperties.getUrl());
        mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
        mysqlXADataSource.setUser(bdpProperties.getUsername());
        Properties properties = druidDatasource.getConnectProperties();
        PasswordDecryptUtil config = new PasswordDecryptUtil();
        mysqlXADataSource.setPassword(config.decryptPassword(properties, bdpProperties.getPassword()));

        AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
        xaDataSource.setXaDataSource(mysqlXADataSource);
        xaDataSource.setMaxPoolSize(bdpProperties.getMaxActive());
        xaDataSource.setMinPoolSize(bdpProperties.getMinIdle());
        xaDataSource.setMaxLifetime(bdpProperties.getMaxWait());
        xaDataSource.setTestQuery(bdpProperties.getValidationQuery());
        xaDataSource.setUniqueResourceName("bdpDatasource");
        return xaDataSource;
    }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

cyh男

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值