当前位置:   article > 正文

【mybatis-plus进阶】多租户场景中多数据源自定义来源dynamic-datasource实现_dynamicdatasource自定义数据源

dynamicdatasource自定义数据源

Springboot+mybatis-plus+dynamic-datasource+Druid 多租户场景中多数据源自定义来源dynamic-datasource实现

0.前言

我们低代码平台是支持多租户的模式,用户在平台上配置了多数据源后,数据源会持久化到低代码的数据库中。多租户场景中多数据源自定义来源 是从数据库中通过查询数据源配置信息表,获取到数据库的链接信息和配置信息,然后利用 dynamic-datasource创建多数据源对象注入到容器里。
在这里插入图片描述

  <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
        <version>${dynamic.datasource.version}</version>
   </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

1. 作者提供了接口

在这里插入图片描述

2. 基于此接口的抽象类实现

 @Bean
    public DynamicDataSourceProvider jdbcDynamicDatasourceProvider(DynamicDataSourceProperties properties) {
        // 获取Primary动态数据源
        Map<String, DataSourceProperty> datasourceMap = properties.getDatasource();
        DataSourceProperty masterDsProperty = datasourceMap.get(properties.getPrimary());
        // 从项目配置文件里配置的主数据源中DB加载要多租户的数据源。我们主要用在低代码场景
        return new AbstractJdbcDataSourceProvider(masterDsProperty.getDriverClassName(),
                masterDsProperty.getUrl(), masterDsProperty.getUsername(), masterDsProperty.getPassword()) {
            @Override
            protected Map<String, DataSourceProperty> executeStmt(Statement statement) {
                Map<String, DataSourceProperty> dataSourcePropertiesMap = null;
                ResultSet rs = null;
                try {
                    dataSourcePropertiesMap = new HashMap<>();
                    // DbConstant.DS_DB_SQL 为查询数据库中配置的多租户的数据源配置信息的SQL如
                    // "SELECT * FROM DATABASE_CONFIG "
              
                    rs = statement.executeQuery(DbConstant.DS_DB_SQL);
                    while (rs.next()) {
                        DataSourceProperty property = new DataSourceProperty();
                        String databaseCode = rs.getString(DbConstant.DatabaseConfigField.DATABASE_CODE);
                        property.setDriverClassName(rs.getString(DbConstant.DatabaseConfigField.DRIVER_CLASS));
                        property.setUrl(rs.getString(DbConstant.DatabaseConfigField.DATABASE_URL));
                        property.setUsername(rs.getString(DbConstant.DatabaseConfigField.USER_NAME));
                        property.setPassword(AESUtil.decrypt(rs.getString(DbConstant.DatabaseConfigField.USER_PASSWORD)));
                        property.setLazy(DS_DATASOURCE_LAZY);
                        // 设置Druid配置
                        String druidConfig = rs.getString(DbConstant.DatabaseConfigField.DRUID_CONFIG);
                        property.setDruid(getDruidConfig(druidConfig));
                        dataSourcePropertiesMap.put(databaseCode, property);
                    }
                } catch (SQLException e) {
                    log.error("查询DB数据源配置异常", e);
                } finally {
                    try {
                        if (rs != null) {
                            rs.close();
                        }
                    } catch (SQLException e) {
                        log.error("数据库ResultSet资源释放异常", e);
                    }
                    try {
                        statement.close();
                    } catch (SQLException e) {
                        log.error("数据库Statement资源释放异常", e);
                    }
                }
                log.info(">>>初始化加载DB库中数据源完成");
                return dataSourcePropertiesMap;
            }
        };
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

自定义负载均衡策略

如下图slave组下有三个数据源,当用户使用slave切换数据源时会使用负载均衡算法。

系统自带了两个负载均衡算法

LoadBalanceDynamicDataSourceStrategy 轮询,是默认的。
RandomDynamicDataSourceStrategy 随机的。

spring:
  datasource:
    dynamic:
      datasource:
        master:
          username: sa
          password: ""
          url: jdbc:h2:mem:test
          driver-class-name: org.h2.Driver
          schema: db/schema.sql
        slave_1:
          username: sa
          password: ""
          url: jdbc:h2:mem:test
          driver-class-name: org.h2.Driver
        slave_2:
          username: sa
          password: ""
          url: jdbc:h2:mem:test
          driver-class-name: org.h2.Driver
        slave_3:
          username: sa
          password: ""
          url: jdbc:h2:mem:test
          driver-class-name: org.h2.Driver
      strategy: com.baomidou.dynamic.datasource.strategy.LoadBalanceDynamicDataSourceStrategy
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

如何自定义

如果默认的两个都不能满足要求,可以参考源码自定义。 暂时只能全局更改。

import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import javax.sql.DataSource;

public class RandomDynamicDataSourceStrategy implements DynamicDataSourceStrategy {
    public RandomDynamicDataSourceStrategy() {
    }

    public DataSource determineDataSource(List<DataSource> dataSources) {
        return (DataSource)dataSources.get(ThreadLocalRandom.current().nextInt(dataSources.size()));
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

多数据源懒启动配置

懒启动:连接池创建出来后并不会立即初始化连接池,等需要使用connection的时候再初始化。

暂时只支持Druid和HikariCp和BeeCp连接池。

主要场景可能适合于数据源很多,又不需要启动立即初始化的情况,可以减少系统启动时间。

缺点在于,如果参数配置有误,则启动的时候不知道,初始化的时候失败,可能一直抛异常。

配置使用

spring:
  datasource:
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候会抛出异常,不启动则使用默认数据源.
      lazy: true #默认false非懒启动,系统加载到数据源立即初始化连接池
      datasource:
        master:
          url: jdbc:mysql://xx.xx.xx.xx:3306/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
          lazy: true #表示这个数据源懒启动
        db1:
          url: jdbc:mysql://xx.xx.xx.xx:3307/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
        db2:
          url: jdbc:mysql://xx.xx.xx.xx:3307/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

3. 参考资料

从3.4.0开始,可以注入多个DynamicDataSourceProvider的Bean以实现同时从多个不同来源加载数据源,注意同名会被覆盖。

  1. dynamic-datasource GitHub 仓库 ↗:dynamic-datasource 的官方 GitHub 仓库,包含源代码、文档和示例等资源。
本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/407605
推荐阅读
相关标签
  

闽ICP备14008679号