This commit is contained in:
2023-07-19 13:25:38 +08:00
parent 94242e17a0
commit aa73abd136
6 changed files with 49 additions and 18 deletions

View File

@ -45,8 +45,10 @@ public class BackupDatasourceContext {
* @param list 数据源集合 * @param list 数据源集合
*/ */
private void set(String tenantId, List<DynamicDataSource> list) { private void set(String tenantId, List<DynamicDataSource> list) {
if (CollUtil.isNotEmpty(list)) {
redisTemplate.opsForValue().set(BACKUP_DATASOURCE_KET + tenantId, list); redisTemplate.opsForValue().set(BACKUP_DATASOURCE_KET + tenantId, list);
} }
}
/** /**
* 添加租户备用数据源 * 添加租户备用数据源
@ -59,6 +61,14 @@ public class BackupDatasourceContext {
if (CollUtil.isEmpty(dataSourceList)) { if (CollUtil.isEmpty(dataSourceList)) {
set(dataSource.getTenantId(), ListUtil.toList(dataSource)); set(dataSource.getTenantId(), ListUtil.toList(dataSource));
} else { } else {
for (DynamicDataSource dynamicDataSource : dataSourceList) {
// 删除原来的
if (dataSource.getUrl().equals(dynamicDataSource.getUrl())
&& dataSource.getTenantId().equals(dynamicDataSource.getTenantId())) {
dataSourceList.remove(dataSource);
break;
}
}
dataSourceList.add(dataSource); dataSourceList.add(dataSource);
set(dataSource.getTenantId(), dataSourceList); set(dataSource.getTenantId(), dataSourceList);
} }
@ -69,13 +79,14 @@ public class BackupDatasourceContext {
List<DynamicDataSource> dataSourceList = get(dynamicDataSource.getTenantId()); List<DynamicDataSource> dataSourceList = get(dynamicDataSource.getTenantId());
if (CollUtil.isNotEmpty(dataSourceList)) { if (CollUtil.isNotEmpty(dataSourceList)) {
for (DynamicDataSource dataSource : dataSourceList) { for (DynamicDataSource dataSource : dataSourceList) {
if (dataSource.getUrl().equals(dynamicDataSource.getUrl())) { if (dataSource.getUrl().equals(dynamicDataSource.getUrl())
&& dataSource.getTenantId().equals(dynamicDataSource.getTenantId())) {
dataSourceList.remove(dataSource); dataSourceList.remove(dataSource);
set(dataSource.getTenantId(), dataSourceList);
break; break;
} }
} }
} }
set(dynamicDataSource.getTenantId(), dataSourceList);
} }
/** /**
@ -99,11 +110,11 @@ public class BackupDatasourceContext {
for (DynamicDataSource dynamicDataSource : dataSourceList) { for (DynamicDataSource dynamicDataSource : dataSourceList) {
if (dataSource.getDatasourceId().equals(dynamicDataSource.getDatasourceId())) { if (dataSource.getDatasourceId().equals(dynamicDataSource.getDatasourceId())) {
dataSourceList.remove(dynamicDataSource); dataSourceList.remove(dynamicDataSource);
dataSourceList.add(dataSource);
break; break;
} }
} }
} }
dataSourceList.add(dataSource);
set(dataSource.getTenantId(), dataSourceList); set(dataSource.getTenantId(), dataSourceList);
} }
} }

View File

@ -60,4 +60,13 @@ public class PrimaryDatasourceContext {
public static void remove(String tenantId) { public static void remove(String tenantId) {
PRIMARY_DATASOURCE_MAP.remove(tenantId); PRIMARY_DATASOURCE_MAP.remove(tenantId);
} }
/**
* 是否存在
*
* @param tenantId 租户ID
*/
public static boolean exist(String tenantId) {
return PRIMARY_DATASOURCE_MAP.containsKey(tenantId);
}
} }

View File

@ -6,6 +6,7 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.io.Serializable; import java.io.Serializable;
import java.util.Objects;
/** /**
* 动态数据源实体 * 动态数据源实体
@ -76,4 +77,5 @@ public class DynamicDataSource implements Serializable {
* 服务器SN * 服务器SN
*/ */
private String serverSn; private String serverSn;
} }

View File

@ -142,10 +142,8 @@ public class OnlineDatasourceMonitor {
return false; return false;
} }
Integer backupIndex = null; DynamicDataSource backDynamicDataSource = null;
for (DynamicDataSource backDatasource : dataSources) {
for (int i = 0; i < dataSources.size(); i++) {
DynamicDataSource backDatasource = dataSources.get(i);
Object dynamicDataSource = DatasourceUtil.buildDataSource(tenantId, backDatasource); Object dynamicDataSource = DatasourceUtil.buildDataSource(tenantId, backDatasource);
// 不是空,说明备用数据源有用 // 不是空,说明备用数据源有用
if (Objects.nonNull(dynamicDataSource)) { if (Objects.nonNull(dynamicDataSource)) {
@ -154,23 +152,20 @@ public class OnlineDatasourceMonitor {
redisService.convertAndSend("test", JSONUtil.toJsonStr(backDatasource)); redisService.convertAndSend("test", JSONUtil.toJsonStr(backDatasource));
// 延迟1s钟 等待其他服务器完成切换 // 延迟1s钟 等待其他服务器完成切换
ThreadUtil.sleep(1000); ThreadUtil.sleep(1000);
backupIndex = i; backDynamicDataSource = backDatasource;
break; break;
} }
} }
if (Objects.nonNull(backupIndex)) {
// 切换成功 // 切换成功
DynamicDataSource dynamicDataSource = dataSources.get(backupIndex); if (Objects.nonNull(backDynamicDataSource)) {
// 更改数据库中该数据源为主要数据源 // 更改数据库中该数据源为主要数据源
if (Objects.nonNull(dynamicDataSource.getTenantId()) && !TenantConstant.DEFAULT_TENANT_ID.equals(dynamicDataSource.getTenantId())) { if (Objects.nonNull(backDynamicDataSource.getTenantId()) && !TenantConstant.DEFAULT_TENANT_ID.equals(backDynamicDataSource.getTenantId())) {
// 添加到待处理任务中 // 添加到待处理任务中
addWaitUpdateDatasourceStatus(dynamicDataSource.getTenantId(), dynamicDataSource.getDatasourceId()); addWaitUpdateDatasourceStatus(backDynamicDataSource.getTenantId(), backDynamicDataSource.getDatasourceId());
} }
// 备用数据源集合删除该数据源 // 备用数据源集合删除该数据源
dataSources.remove((int) backupIndex); backupDatasourceContext.deleteBackupMap(backDynamicDataSource);
backupDatasourceContext.addBackupMap(tenantId, dataSources); log.info("租户:[{}]切换备用数据源成功, 现主数据ID: {}", tenantId, backDynamicDataSource.getDatasourceId());
log.info("租户:[{}]切换备用数据源成功, 现主数据ID: {}", tenantId, dynamicDataSource.getDatasourceId());
return true; return true;
} else { } else {
log.error("租户:[{}]切换备用数据源失败, 原因: 备用数据源均无效", tenantId); log.error("租户:[{}]切换备用数据源失败, 原因: 备用数据源均无效", tenantId);

View File

@ -32,6 +32,8 @@ public class JdbcUtil {
Connection conn = null; Connection conn = null;
try { try {
Class.forName(driver); Class.forName(driver);
// 设置两秒延时 默认10s
DriverManager.setLoginTimeout(2);
//建立连接 //建立连接
conn = DriverManager.getConnection(url, username, password); conn = DriverManager.getConnection(url, username, password);
return true; return true;

View File

@ -3,14 +3,17 @@ package com.qiaoba.module.tenant.filter;
import cn.hutool.core.collection.ListUtil; import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import com.qiaoba.api.tenant.entity.SysTenant; import com.qiaoba.api.tenant.entity.SysTenant;
import com.qiaoba.api.tenant.enums.TenantModeEnum;
import com.qiaoba.api.tenant.enums.TenantStatusEnum; import com.qiaoba.api.tenant.enums.TenantStatusEnum;
import com.qiaoba.api.tenant.utils.TenantUtil; import com.qiaoba.api.tenant.utils.TenantUtil;
import com.qiaoba.common.base.code.DatasourceErrorCode;
import com.qiaoba.common.base.code.TenantErrorCode; import com.qiaoba.common.base.code.TenantErrorCode;
import com.qiaoba.common.base.constant.BaseConstant; import com.qiaoba.common.base.constant.BaseConstant;
import com.qiaoba.common.base.constant.TenantConstant; import com.qiaoba.common.base.constant.TenantConstant;
import com.qiaoba.common.base.context.BaseContext; import com.qiaoba.common.base.context.BaseContext;
import com.qiaoba.common.base.order.FilterOrder; import com.qiaoba.common.base.order.FilterOrder;
import com.qiaoba.common.database.config.DynamicDataSourceConfig; import com.qiaoba.common.database.config.DynamicDataSourceConfig;
import com.qiaoba.common.database.context.PrimaryDatasourceContext;
import com.qiaoba.common.web.util.ResponseUtil; import com.qiaoba.common.web.util.ResponseUtil;
import com.qiaoba.common.web.util.UriUtil; import com.qiaoba.common.web.util.UriUtil;
import com.qiaoba.module.tenant.service.SysTenantService; import com.qiaoba.module.tenant.service.SysTenantService;
@ -61,6 +64,7 @@ public class DynamicDataSourceFilter extends OncePerRequestFilter {
try { try {
log.debug("Start run DynamicDataSourceFilter, Uri: {}", request.getRequestURI()); log.debug("Start run DynamicDataSourceFilter, Uri: {}", request.getRequestURI());
String tenantId = request.getHeader(TenantConstant.HEADER_KEY_TENANT); String tenantId = request.getHeader(TenantConstant.HEADER_KEY_TENANT);
// 主系统 or 登录入口获取租户列表 // 主系统 or 登录入口获取租户列表
if (TenantConstant.DEFAULT_TENANT_ID.equals(tenantId) || TenantConstant.LOGIN_TENANT_LIST_URI.equals(request.getRequestURI())) { if (TenantConstant.DEFAULT_TENANT_ID.equals(tenantId) || TenantConstant.LOGIN_TENANT_LIST_URI.equals(request.getRequestURI())) {
dynamicDataSourceConfig.setDefaultSetting(); dynamicDataSourceConfig.setDefaultSetting();
@ -113,6 +117,14 @@ public class DynamicDataSourceFilter extends OncePerRequestFilter {
return true; return true;
} }
// 检查租户数据源是否正常
if (TenantModeEnum.isDatasource(sysTenant.getMode())
&& !PrimaryDatasourceContext.exist(sysTenant.getTenantId())) {
// 无主数据
log.debug("租户数据源不可用, 租户ID: {}", sysTenant.getTenantId());
ResponseUtil.errorAuth(response, DatasourceErrorCode.CONNECT_ERROR.getCode(), DatasourceErrorCode.CONNECT_ERROR.getMsg());
return true;
}
if (TenantStatusEnum.isDisable(sysTenant.getStatus())) { if (TenantStatusEnum.isDisable(sysTenant.getStatus())) {
// 封禁状态 // 封禁状态
log.debug("租户已封禁, 租户ID: {}", sysTenant.getTenantId()); log.debug("租户已封禁, 租户ID: {}", sysTenant.getTenantId());