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

View File

@ -60,4 +60,13 @@ public class PrimaryDatasourceContext {
public static void remove(String 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 java.io.Serializable;
import java.util.Objects;
/**
* 动态数据源实体
@ -76,4 +77,5 @@ public class DynamicDataSource implements Serializable {
* 服务器SN
*/
private String serverSn;
}

View File

@ -142,10 +142,8 @@ public class OnlineDatasourceMonitor {
return false;
}
Integer backupIndex = null;
for (int i = 0; i < dataSources.size(); i++) {
DynamicDataSource backDatasource = dataSources.get(i);
DynamicDataSource backDynamicDataSource = null;
for (DynamicDataSource backDatasource : dataSources) {
Object dynamicDataSource = DatasourceUtil.buildDataSource(tenantId, backDatasource);
// 不是空,说明备用数据源有用
if (Objects.nonNull(dynamicDataSource)) {
@ -154,23 +152,20 @@ public class OnlineDatasourceMonitor {
redisService.convertAndSend("test", JSONUtil.toJsonStr(backDatasource));
// 延迟1s钟 等待其他服务器完成切换
ThreadUtil.sleep(1000);
backupIndex = i;
backDynamicDataSource = backDatasource;
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.addBackupMap(tenantId, dataSources);
log.info("租户:[{}]切换备用数据源成功, 现主数据ID: {}", tenantId, dynamicDataSource.getDatasourceId());
backupDatasourceContext.deleteBackupMap(backDynamicDataSource);
log.info("租户:[{}]切换备用数据源成功, 现主数据ID: {}", tenantId, backDynamicDataSource.getDatasourceId());
return true;
} else {
log.error("租户:[{}]切换备用数据源失败, 原因: 备用数据源均无效", tenantId);

View File

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

View File

@ -3,14 +3,17 @@ package com.qiaoba.module.tenant.filter;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
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.utils.TenantUtil;
import com.qiaoba.common.base.code.DatasourceErrorCode;
import com.qiaoba.common.base.code.TenantErrorCode;
import com.qiaoba.common.base.constant.BaseConstant;
import com.qiaoba.common.base.constant.TenantConstant;
import com.qiaoba.common.base.context.BaseContext;
import com.qiaoba.common.base.order.FilterOrder;
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.UriUtil;
import com.qiaoba.module.tenant.service.SysTenantService;
@ -61,6 +64,7 @@ public class DynamicDataSourceFilter extends OncePerRequestFilter {
try {
log.debug("Start run DynamicDataSourceFilter, Uri: {}", request.getRequestURI());
String tenantId = request.getHeader(TenantConstant.HEADER_KEY_TENANT);
// 主系统 or 登录入口获取租户列表
if (TenantConstant.DEFAULT_TENANT_ID.equals(tenantId) || TenantConstant.LOGIN_TENANT_LIST_URI.equals(request.getRequestURI())) {
dynamicDataSourceConfig.setDefaultSetting();
@ -113,6 +117,14 @@ public class DynamicDataSourceFilter extends OncePerRequestFilter {
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())) {
// 封禁状态
log.debug("租户已封禁, 租户ID: {}", sysTenant.getTenantId());