From fc533fa2e8164185f37735ac164a79dfe5ceb3ea Mon Sep 17 00:00:00 2001 From: ailanyin Date: Thu, 15 Jun 2023 17:46:38 +0800 Subject: [PATCH] add --- .../config/DynamicDataSourceConfig.java | 39 ++++++++++--------- .../config/DynamicDataSourceContext.java | 3 +- .../constants/DynamicDatasourceConstant.java | 22 ----------- .../monitor/DatasourceConnectionMonitor.java | 31 +++++++++------ .../common/database/utils/JdbcUtil.java | 4 +- .../filters/DynamicDataSourceFilter.java | 6 +-- 6 files changed, 46 insertions(+), 59 deletions(-) delete mode 100644 qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/constants/DynamicDatasourceConstant.java diff --git a/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/config/DynamicDataSourceConfig.java b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/config/DynamicDataSourceConfig.java index 4ad4dd5..b6206ee 100644 --- a/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/config/DynamicDataSourceConfig.java +++ b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/config/DynamicDataSourceConfig.java @@ -2,12 +2,12 @@ package com.qiaoba.common.database.config; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.io.IoUtil; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.pool.DruidPooledConnection; import com.qiaoba.common.base.constants.TenantConstant; import com.qiaoba.common.base.context.BaseContext; import com.qiaoba.common.base.enums.BaseEnum; -import com.qiaoba.common.database.constants.DynamicDatasourceConstant; import com.qiaoba.common.database.entity.DynamicDataSource; import com.qiaoba.common.database.properties.DataSourceProperties; import com.qiaoba.common.database.service.DynamicDatasourceService; @@ -18,6 +18,7 @@ import org.springframework.context.annotation.Configuration; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.annotation.Resource; +import java.sql.SQLException; import java.util.List; import java.util.Map; import java.util.Objects; @@ -83,13 +84,13 @@ public class DynamicDataSourceConfig { } public static DruidDataSource getPrimaryDataSource(String tenantId) { - return (DruidDataSource) PRIMARY_DATASOURCE_MAP.get(DynamicDatasourceConstant.MASTER_PREFIX + tenantId); + return (DruidDataSource) PRIMARY_DATASOURCE_MAP.get(tenantId); } private void initDefault() { List dataSources = dataSourceProperties.getDataSources(); // 0索引作为主数据源 - addPrimaryMap(DynamicDatasourceConstant.MASTER_PREFIX + TenantConstant.DEFAULT_TENANT_ID, buildDataSource(TenantConstant.DEFAULT_TENANT_ID, dataSources.get(0))); + addPrimaryMap(TenantConstant.DEFAULT_TENANT_ID, buildDataSource(TenantConstant.DEFAULT_TENANT_ID, dataSources.get(0))); dataSources.remove(0); // 非0索引的备用 addBackupMap(TenantConstant.DEFAULT_TENANT_ID, dataSources); @@ -105,7 +106,7 @@ public class DynamicDataSourceConfig { for (int i = 0; i < dataSources.size(); i++) { DynamicDataSource dynamicDataSource = dataSources.get(i); if (BaseEnum.YES.getCode().equals(dynamicDataSource.getIsPrimary())) { - addPrimaryMap(DynamicDatasourceConstant.MASTER_PREFIX + tenantId, buildDataSource(dataSources.get(i).getTenantId(), dataSources.get(i))); + addPrimaryMap(tenantId, buildDataSource(dataSources.get(i).getTenantId(), dataSources.get(i))); // 去除主要数据源,剩下皆为备用数据源 dataSources.remove(i); break; @@ -122,12 +123,12 @@ public class DynamicDataSourceConfig { } public void deleteTenantDataSource(String tenantId) { - PRIMARY_DATASOURCE_MAP.remove(DynamicDatasourceConstant.MASTER_PREFIX + tenantId); + PRIMARY_DATASOURCE_MAP.remove(tenantId); dataSource.freshDataSource(PRIMARY_DATASOURCE_MAP); } public void changePrimaryDatasource(String tenantId, Object datasource) { - PRIMARY_DATASOURCE_MAP.put(DynamicDatasourceConstant.MASTER_PREFIX + tenantId, datasource); + PRIMARY_DATASOURCE_MAP.put(tenantId, datasource); dataSource.freshDataSource(PRIMARY_DATASOURCE_MAP); } @@ -150,14 +151,9 @@ public class DynamicDataSourceConfig { try { // 初始化数据源 dataSource.init(); - // 将数据源的类型保存 - DruidPooledConnection connection = dataSource.getConnection(); - TENANT_DATASOURCE_TYPE_MAP.put(tenantId, connection.getMetaData().getDatabaseProductName()); - // 归还 connection - connection.close(); return dataSource; } catch (Exception e) { - dataSource.close(); + IoUtil.close(dataSource); return null; } } @@ -170,15 +166,22 @@ public class DynamicDataSourceConfig { Set> entries = PRIMARY_DATASOURCE_MAP.entrySet(); for (Map.Entry entry : entries) { DruidDataSource dataSource = (DruidDataSource) entry.getValue(); - if (!dataSource.isClosed()) { - dataSource.close(); - } + IoUtil.close(dataSource); } } - private void addPrimaryMap(String name, Object dataSource) { + private void addPrimaryMap(String tenantId, Object dataSource) { if (Objects.nonNull(dataSource)) { - PRIMARY_DATASOURCE_MAP.put(name, dataSource); + try { + PRIMARY_DATASOURCE_MAP.put(tenantId, dataSource); + // 将数据源的类型保存 + DruidPooledConnection connection = ((DruidDataSource) dataSource).getConnection(); + TENANT_DATASOURCE_TYPE_MAP.put(tenantId, connection.getMetaData().getDatabaseProductName()); + // 归还 connection + IoUtil.close(connection); + } catch (SQLException e) { + e.printStackTrace(); + } } } @@ -194,7 +197,7 @@ public class DynamicDataSourceConfig { } public void setDefaultSetting() { - BaseContext.setDataSource(DynamicDatasourceConstant.MASTER_PREFIX + TenantConstant.DEFAULT_TENANT_ID); + BaseContext.setDataSource(TenantConstant.DEFAULT_TENANT_ID); BaseContext.setTenantId(TenantConstant.DEFAULT_TENANT_ID); BaseContext.setDatabaseType(TENANT_DATASOURCE_TYPE_MAP.get(TenantConstant.DEFAULT_TENANT_ID)); } diff --git a/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/config/DynamicDataSourceContext.java b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/config/DynamicDataSourceContext.java index 55a39d2..1ab838e 100644 --- a/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/config/DynamicDataSourceContext.java +++ b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/config/DynamicDataSourceContext.java @@ -2,7 +2,6 @@ package com.qiaoba.common.database.config; import com.qiaoba.common.base.constants.TenantConstant; import com.qiaoba.common.base.context.BaseContext; -import com.qiaoba.common.database.constants.DynamicDatasourceConstant; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; import java.util.Map; @@ -22,7 +21,7 @@ public class DynamicDataSourceContext extends AbstractRoutingDataSource { */ public void freshDataSource(Map targetDataSources) { //默认数据源 (determineCurrentLookupKey 如果找不到就使用默认数据源) - super.setDefaultTargetDataSource(targetDataSources.get(DynamicDatasourceConstant.MASTER_PREFIX + TenantConstant.DEFAULT_TENANT_ID)); + super.setDefaultTargetDataSource(targetDataSources.get(TenantConstant.DEFAULT_TENANT_ID)); //设置全部数据源 super.setTargetDataSources(targetDataSources); //刷新(即把targetDataSources刷到resolvedDataSources中去,resolvedDataSources才是我们真正存放数据源的map) diff --git a/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/constants/DynamicDatasourceConstant.java b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/constants/DynamicDatasourceConstant.java deleted file mode 100644 index 98b9dee..0000000 --- a/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/constants/DynamicDatasourceConstant.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.qiaoba.common.database.constants; - -/** - * DynamicDatasourceConstant - * - * @author ailanyin - * @version 1.0 - * @since 2023-04-27 19:35:28 - */ -public class DynamicDatasourceConstant { - - /** - * 主数据源拼接前缀 master_tenantId - */ - public static final String MASTER_PREFIX = "master_"; - - /** - * 从数据源拼接前缀 slave_tenantId_序号 - */ - public static final String SLAVE_PREFIX = "slave_"; - -} diff --git a/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/monitor/DatasourceConnectionMonitor.java b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/monitor/DatasourceConnectionMonitor.java index f90fd9d..beefef4 100644 --- a/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/monitor/DatasourceConnectionMonitor.java +++ b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/monitor/DatasourceConnectionMonitor.java @@ -1,10 +1,9 @@ package com.qiaoba.common.database.monitor; +import cn.hutool.core.io.IoUtil; import com.alibaba.druid.pool.DruidDataSource; -import com.alibaba.druid.util.JdbcUtils; import com.qiaoba.common.base.constants.TenantConstant; import com.qiaoba.common.database.config.DynamicDataSourceConfig; -import com.qiaoba.common.database.constants.DynamicDatasourceConstant; import com.qiaoba.common.database.entity.DynamicDataSource; import com.qiaoba.common.database.service.DynamicDatasourceService; import lombok.extern.slf4j.Slf4j; @@ -17,6 +16,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; /** * 监控-数据源连接监控 @@ -36,6 +36,8 @@ public class DatasourceConnectionMonitor { @Resource private DynamicDatasourceService dynamicDatasourceService; + private static Map WAIT_UPDATE_DATASOURCE_STATUS = new ConcurrentHashMap<>(); + @PostConstruct public void init() { new Timer().schedule(new TimerTask() { @@ -45,9 +47,9 @@ public class DatasourceConnectionMonitor { if (!DynamicDataSourceConfig.COMPLETE_LOAD_DATASOURCE) { return; } - log.debug("开始运行数据源监控线程, 时间: {}", new Date()); + log.trace("开始运行数据源监控线程, 时间: {}", new Date()); for (String tenantId : DynamicDataSourceConfig.TENANT_IDS) { - Object primary = DynamicDataSourceConfig.PRIMARY_DATASOURCE_MAP.get(DynamicDatasourceConstant.MASTER_PREFIX + tenantId); + Object primary = DynamicDataSourceConfig.PRIMARY_DATASOURCE_MAP.get(tenantId); if (Objects.isNull(primary)) { // 说明初始化主要数据源的时候出错 log.error("租户[{}]-目前主数据源异常, 开始切换备用数据源", tenantId); @@ -59,17 +61,17 @@ public class DatasourceConnectionMonitor { Connection connection = dataSource.getConnection(); if (check(connection)) { // 说明数据源正常 - log.debug("租户[{}]-目前主数据源正常, 无需切换数据源", tenantId); - connection.close(); + log.trace("租户[{}]-目前主数据源正常, 无需切换数据源", tenantId); + IoUtil.close(connection); continue; } log.error("租户[{}]-目前主数据源异常, 开始切换备用数据源", tenantId); - connection.close(); + IoUtil.close(connection); // 主数据源异常 切换备用数据源 if (changePrimary(tenantId)) { // 备用切换成功, 关闭原有异常数据源 - dataSource.close(); + IoUtil.close(dataSource); } } catch (SQLException e) { e.printStackTrace(); @@ -77,7 +79,7 @@ public class DatasourceConnectionMonitor { } } - log.debug("结束运行数据源监控线程, 时间: {}", new Date()); + log.trace("结束运行数据源监控线程, 时间: {}", new Date()); } }, 0, 1000); } @@ -93,8 +95,8 @@ public class DatasourceConnectionMonitor { } catch (Exception e) { return false; } finally { - JdbcUtils.close(rs); - JdbcUtils.close(stmt); + IoUtil.close(rs); + IoUtil.close(stmt); } } @@ -128,7 +130,12 @@ public class DatasourceConnectionMonitor { DynamicDataSource dynamicDataSource = dataSources.get(backupIndex); // 更改数据库中该数据源为主要数据源 if (!TenantConstant.DEFAULT_TENANT_ID.equals(dynamicDataSource.getTenantId())) { - dynamicDatasourceService.changePrimaryDatasource(dynamicDataSource.getTenantId(), dynamicDataSource.getDatasourceId()); + try { + dynamicDatasourceService.changePrimaryDatasource(dynamicDataSource.getTenantId(), dynamicDataSource.getDatasourceId()); + } catch (Exception e) { + // 说明主数据源也挂了 + WAIT_UPDATE_DATASOURCE_STATUS.put(dynamicDataSource.getTenantId(), dynamicDataSource.getDatasourceId()); + } } // 备用数据源集合删除该数据源 dataSources.remove((int) backupIndex); diff --git a/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/utils/JdbcUtil.java b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/utils/JdbcUtil.java index 382cb64..b3f16b9 100644 --- a/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/utils/JdbcUtil.java +++ b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/utils/JdbcUtil.java @@ -3,6 +3,7 @@ package com.qiaoba.common.database.utils; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.StrUtil; import com.qiaoba.common.base.exceptions.ServiceException; +import lombok.extern.slf4j.Slf4j; import java.sql.Connection; import java.sql.DriverManager; @@ -14,6 +15,7 @@ import java.sql.DriverManager; * @version 1.0 * @since 2021/10/15 0015 下午 16:43 */ +@Slf4j public class JdbcUtil { /** @@ -33,7 +35,7 @@ public class JdbcUtil { conn = DriverManager.getConnection(url, username, password); return true; } catch (Exception e) { - e.printStackTrace(); + log.debug(e.getMessage()); return false; } finally { IoUtil.close(conn); diff --git a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/filters/DynamicDataSourceFilter.java b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/filters/DynamicDataSourceFilter.java index 5ffebe6..9a61afe 100644 --- a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/filters/DynamicDataSourceFilter.java +++ b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/filters/DynamicDataSourceFilter.java @@ -3,11 +3,9 @@ package com.qiaoba.module.tenant.filters; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.date.DateUtil; import com.qiaoba.common.base.code.TenantErrorCode; -import com.qiaoba.common.base.constants.BaseConstant; import com.qiaoba.common.base.constants.TenantConstant; import com.qiaoba.common.base.context.BaseContext; import com.qiaoba.common.database.config.DynamicDataSourceConfig; -import com.qiaoba.common.database.constants.DynamicDatasourceConstant; import com.qiaoba.common.web.utils.ResponseUtil; import com.qiaoba.common.web.utils.UriUtil; import com.qiaoba.module.tenant.entity.SysTenant; @@ -86,12 +84,12 @@ public class DynamicDataSourceFilter extends OncePerRequestFilter { // 数据源模式-设置第三方数据源 if (sysTenant.getMode().equals(SysTenant.DATASOURCE_MODE)) { //设置当前租户对应的数据源 - BaseContext.setDataSource(DynamicDatasourceConstant.MASTER_PREFIX + sysTenant.getTenantId()); + BaseContext.setDataSource(sysTenant.getTenantId()); BaseContext.setDatabaseType(DynamicDataSourceConfig.TENANT_DATASOURCE_TYPE_MAP.get(sysTenant.getTenantId())); } // 字段模式 or Schema模式-数据源选择默认数据源 else { - BaseContext.setDataSource(DynamicDatasourceConstant.MASTER_PREFIX + TenantConstant.DEFAULT_TENANT_ID); + BaseContext.setDataSource(TenantConstant.DEFAULT_TENANT_ID); BaseContext.setDatabaseType(DynamicDataSourceConfig.TENANT_DATASOURCE_TYPE_MAP.get(TenantConstant.DEFAULT_TENANT_ID)); }