动态数据源配置连接数未生效


highlight: arduino-light

最近开发环境总是遇到 Got minus one from a read call 的报错。

排查思路: 首先怀疑可能是连接数达到上限,于是尝试修改数据库最大连接和最小连接。

yml spring: datasource: # 数据源的相关配置 dynamic: primary: master #设置默认的数据源或者数据源组,默认值即为master strict: false #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候会抛出异常,不启动则使用默认数据源. datasource: master: type: com.zaxxer.hikari.HikariDataSource # 数据源类型:HikariCP driver-class-name: oracle.jdbc.OracleDriver url: jdbc:oracle:thin:@xxxxx:1521/xxxxx username: xxxxx password: xxxxx hikari: connection-timeout: 30000 # 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQ minimum-idle: 5 # 最小连接数 maximum-pool-size: 10 # 最大连接数 auto-commit: true # 自动提交 idle-timeout: 600000 # 连接超时的最大时长(毫秒),超时则被释放(retired),默认:10分钟 pool-name: BoxServerApiPool # 连接池名字 max-lifetime: 1800000 # 连接的生命时长(毫秒),超时而且没被使用则被释放(retired),默认:30分钟 connection-test-query: SELECT 1 data-source-properties: #以下属性仅为演示(默认不会引入) serverTimezone: Asia/Shanghai

但是发现竟然没有起作用,经过排查发现配置的最大连接数和最小连接数都是10.并不是我们配置的5和10,遂开启了bug排查之路。

首先我们使用的数据源是动态数据源,对应的依赖版本:dynamic-datasource-spring-boot-starter-3.3.1。

DynamicDataSourceAutoConfiguration是动态数据源的自动配置类。

```java

@Configuration @EnableConfigurationProperties({DynamicDataSourceProperties.class}) @AutoConfigureBefore({DataSourceAutoConfiguration.class}) @Import({DruidDynamicDataSourceConfiguration.class, DynamicDataSourceCreatorAutoConfiguration.class}) @ConditionalOnProperty( prefix = "spring.datasource.dynamic", name = {"enabled"}, havingValue = "true", matchIfMissing = true ) public class DynamicDataSourceAutoConfiguration { DynamicDataSourceProperties properties; } ```

读取前缀为 spring.datasource.dynamic的属性,封装到DynamicDataSourceAutoConfiguration#的成员变量DynamicDataSourceProperties;

java @ConfigurationProperties( prefix = "spring.datasource.dynamic" ) public class DynamicDataSourceProperties { }

使用配置文件中的spring.datasource.dynamic.datasource属性构建DynamicDataSourceProvider

java @Bean @ConditionalOnMissingBean public DynamicDataSourceProvider dynamicDataSourceProvider() { Map<String, DataSourceProperty> datasourceMap = this.properties.getDatasource(); return new YmlDynamicDataSourceProvider(datasourceMap); }

com.baomidou.dynamic.datasource.DynamicRoutingDataSource#setProvider

java public void setProvider(DynamicDataSourceProvider provider) { this.provider = provider; }

​ com.baomidou.dynamic.datasource.provider.YmlDynamicDataSourceProvider#loadDataSources

java public Map<String, DataSource> loadDataSources() { return this.createDataSourceMap(this.dataSourcePropertiesMap); }

com.baomidou.dynamic.datasource.provider.AbstractDataSourceProvider#createDataSourceMap

使用配置文件中的配置创建数据源

image.png

```java protected Map createDataSourceMap(Map dataSourcePropertiesMap) { Map dataSourceMap = new HashMap(dataSourcePropertiesMap.size() * 2); Iterator var3 = dataSourcePropertiesMap.entrySet().iterator();

while(var3.hasNext()) {
        Entry<String, DataSourceProperty> item = (Entry)var3.next();
        DataSourceProperty dataSourceProperty = (DataSourceProperty)item.getValue();
        String poolName = dataSourceProperty.getPoolName();
        if (poolName == null || "".equals(poolName)) {
            poolName = (String)item.getKey();
        }

        dataSourceProperty.setPoolName(poolName);
        //创建数据源放入Map
        dataSourceMap.put(poolName, this.defaultDataSourceCreator.createDataSource(dataSourceProperty));
    }

    return dataSourceMap;
}

```

java @Override public DataSource createDataSource(DataSourceProperty dataSourceProperty) { return createDataSource(dataSourceProperty, properties.getPublicKey()); }

根据不同的dataSourceProperty选择不同的DataSourceCreator,然后使用DataSourceCreator创建对应的数据源。

```java @Override public DataSource createDataSource(DataSourceProperty dataSourceProperty, String publicKey) { DataSourceCreator dataSourceCreator = null;

/***

    典型的策略模式会使用map存放策略,根据不同的key选择策略。
    所有的策略实现了同1个接口,策略方法的出参/入参相同。

    此处也是策略模式,spring源码中也出现过类似的用法。
    support()方法主要用于判断各个子类是否支持当前类型数据的处理即判断策略是否适配当前场景。

    2种策略模式的区别:选择策略的方式不同。

    createDataSource()方法主要用于创建具体的dataSource
    ****/
    for (DataSourceCreator creator : this.creators) {
        if (creator.support(dataSourceProperty)) {
            dataSourceCreator = creator;
            break;
        }
    }
    if (dataSourceCreator == null) {
        throw new IllegalStateException("creator must not be null,please check the DataSourceCreator");
    }
    DataSource dataSource = dataSourceCreator.createDataSource(dataSourceProperty, publicKey);
    this.runScrip(dataSource, dataSourceProperty);
    return wrapDataSource(dataSource, dataSourceProperty);
}

support方法 java @Override public boolean support(DataSourceProperty dataSourceProperty) { Class extends DataSource> type = dataSourceProperty.getType(); return (type == null && hikariExists) || (type != null && HIKARI_DATASOURCE.equals(type.getName())); } ```

``` 而我们用的是hikari的数据源,对应的creator就是HikariDataSourceCreator。

com.baomidou.dynamic.datasource.creator.HikariDataSourceCreator#createDataSource

java public DataSource createDataSource(DataSourceProperty dataSourceProperty, String publicKey) { if (StringUtils.isEmpty(dataSourceProperty.getPublicKey())) { dataSourceProperty.setPublicKey(publicKey); } //关键代码在这里 会将配置中文件中的配置转换为HikariConfig HikariConfig config = dataSourceProperty.getHikari().toHikariConfig(this.hikariCpConfig); config.setUsername(dataSourceProperty.getUsername()); config.setPassword(dataSourceProperty.getPassword()); config.setJdbcUrl(dataSourceProperty.getUrl()); config.setPoolName(dataSourceProperty.getPoolName()); String driverClassName = dataSourceProperty.getDriverClassName(); if (!StringUtils.isEmpty(driverClassName)) { config.setDriverClassName(driverClassName); } //使用HikariConfig构建数据源 return new HikariDataSource(config); }

知道了原理,去修改配置文件就行了

yml spring: datasource: # 数据源的相关配置 dynamic: primary: master #设置默认的数据源或者数据源组,默认值即为master strict: false #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候会抛出异常,不启动则使用默认数据源. datasource: master: type: com.zaxxer.hikari.HikariDataSource # 数据源类型:HikariCP driver-class-name: oracle.jdbc.OracleDriver url: jdbc:oracle:thin:@xxxxx:1521/xxxxx username: xxxxx password: xxxxx hikari: connection-timeout: 30000 # 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQ minIdle: 5 # 最小连接数 maxPoolSize: 10 # 最大连接数 isAutoCommit: true # 自动提交 idleTimeout: 600000 # 连接超时的最大时长(毫秒),超时则被释放(retired),默认:10分钟 poolName: BoxServerApiPool # 连接池名字 maxLifetime: 1800000 # 连接的生命时长(毫秒),超时而且没被使用则被释放(retired),默认:30分钟 connection-test-query: SELECT 1 FROM DUAL data-source-properties: #以下属性仅为演示(默认不会引入) serverTimezone: Asia/Shanghai

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 如果 MyBatis-Plus 多数据源失效,可以尝试以下步骤: 1. 检查配置文件是否正确 在配置文件中检查是否正确配置了多个数据源,并且每个数据源配置是否正确。 2. 检查数据源是否可用 检查数据源是否可用,可以使用 JDBC 连接测试工具测试连接是否成功。 3. 检查数据源的 Mapper 是否正确 检查每个数据源的 Mapper 是否正确配置,包括 Mapper 接口和 XML 文件。 4. 检查数据源的事务管理器是否正确 如果使用了多个数据源,必须为每个数据源配置一个事务管理器。检查每个数据源的事务管理器是否正确配置。 5. 检查数据源动态切换是否正确 如果使用了动态数据源切换,需要检查切换逻辑是否正确,如切换策略、切换时机等。 如果以上步骤都检查过了,还是无法解决问题,可以考虑查看日志或调试程序,找到具体的错误原因。 ### 回答2: MyBatis Plus是一个功能强大的ORM框架,可以简化和提高数据库操作的效率。但在使用多数据源时,可能会遇到失效的情况。解决问题的方法如下: 1. 检查配置文件:首先,检查配置文件中的数据源配置是否正确。确保每个数据源配置信息都正确且没有错误。常见的错误包括:数据库连接地址、用户名、密码等。 2. 检查数据库连接池配置:如果使用了连接池,确保连接池的配置正确。比如,连接池的最大连接数、最小空闲连接数等。 3. 检查数据源的初始化顺序:多个数据源的初始化顺序可能会影响数据源的使用。确保数据源的初始化顺序是正确的,按需加载数据源。 4. 检查数据源的命名规范:多数据源的命名规范需要统一,确保各个数据源的名称不会冲突。这样,MyBatis Plus可以根据数据源的名称选择对应的数据源进行操作。 5. 使用@MapperScan注解:在配置MyBatis Plus的扫描注解@MapperScan时,确保指定了正确的数据源。@MapperScan注解可以指定要扫描的包路径,并将其与指定的数据源关联起来。 6. 检查Mapper类的注解:在Mapper类中,使用@Mapper注解将该类与对应的数据源进行关联。确保注解中的数据源与实际使用的数据源保持一致。 7. 检查事务注解:在使用多数据源时,事务注解的使用需要注意。确保事务注解在需要开启事务的地方正确地使用,并且与对应的数据源关联起来。 总之,当MyBatis Plus的多数据源失效时,我们可以通过检查配置文件、连接池配置数据源初始化顺序、命名规范、注解等多个方面来排查问题并进行修复。 ### 回答3: 当MyBatis Plus多数据源失效时,可以按照以下步骤进行排查和解决: 1. 检查数据源配置: 确认多数据源配置是否正确,包括数据库驱动、URL、用户名和密码等。如果有错误或遗漏,修正配置文件。 2. 检查依赖配置: 确认项目依赖中是否正确引入了多数据源相关的依赖包。如果没有引入或依赖版本不兼容,修正依赖配置并重新构建项目。 3. 检查数据库连接: 确认多数据源对应的数据库连接是否可用。可以通过尝试连接数据库并执行简单查询语句来确认连接是否正常。如果连接失败,可以检查网络、数据库服务是否正常启动或配置是否正确。 4. 检查数据源切换: MyBatis Plus提供了多种方式进行数据源切换,例如使用注解、配置文件等。确认数据源切换的方式是否正确,并验证切换逻辑是否生效。 5. 检查Mapper接口配置: 确认Mapper接口的注解或配置是否正确,包括接口绑定的数据源是否与实际的多数据源一致,以及是否有其他的冲突。 6. 检查事务管理: 如果在多数据源环境下使用了事务管理,需要确保事务管理器配置正确,并且事务的注解或配置与多数据源配置没有冲突。 7. 检查日志输出: 开启MyBatis Plus的日志输出,查看是否有相关的错误或异常信息。根据日志内容进行问题排查或查找解决方案。 如果按照上述步骤检查并排除了可能的问题,但多数据源依然失效,可以考虑查看MyBatis Plus的官方文档、社区论坛或提交Github的issue,以获取更详细的帮助和解决方案。

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值