feat: 服务资源配置文件增加多租户混合模式负载均衡配置
## application-docker.yml 更新 ### fund-sys - Nacos 元数据配置:tenant-id, tenant-group - 租户路由配置:启用租户感知负载均衡 - VIP 租户列表定义 - 监控标签:tenant_id, tenant_group, instance_type - 日志格式:增加 tenantId MDC ### fund-gateway - 全局跨域配置 - 多租户路由配置(所有服务的VIP租户列表) - 监控和日志增强 ## TenantRoutingProperties 更新 - 添加 @ConfigurationProperties 支持 YAML 配置绑定 - 新增 vip-tenants 列表属性 - 新增 fallback-to-shared 回退策略属性 - 新增 getVipTenants(), isVipTenant(), isFallbackToShared() 方法
This commit is contained in:
parent
5843cc050e
commit
2c0f2f8952
@ -3,14 +3,32 @@ package com.fundplatform.common.config;
|
|||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
/**
|
||||||
import java.util.HashMap;
|
* 多租户路由配置属性
|
||||||
|
*
|
||||||
|
* <p>支持从 YAML 配置文件读取租户路由配置</p>
|
||||||
|
*
|
||||||
|
* <p>配置示例:</p>
|
||||||
|
* <pre>
|
||||||
|
* tenant:
|
||||||
|
* routing:
|
||||||
|
* enabled: true
|
||||||
|
* default-tenant-id: 1
|
||||||
|
* services:
|
||||||
|
* fund-sys:
|
||||||
|
* vip-tenants:
|
||||||
|
* - TENANT_VIP_001
|
||||||
|
* fallback-to-shared: true
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "tenant.routing")
|
||||||
public class TenantRoutingProperties {
|
public class TenantRoutingProperties {
|
||||||
|
|
||||||
/** 是否启用租户路由 */
|
/** 是否启用租户路由 */
|
||||||
private boolean enabled = false;
|
private boolean enabled = true;
|
||||||
|
|
||||||
/** 租户 ID 请求头 */
|
/** 租户 ID 请求头 */
|
||||||
private String tenantHeader = "X-Tenant-Id";
|
private String tenantHeader = "X-Tenant-Id";
|
||||||
@ -21,6 +39,9 @@ public class TenantRoutingProperties {
|
|||||||
/** 服务组分隔符 */
|
/** 服务组分隔符 */
|
||||||
private String groupSeparator = "TENANT_";
|
private String groupSeparator = "TENANT_";
|
||||||
|
|
||||||
|
/** 默认租户 ID(当未指定时使用) */
|
||||||
|
private String defaultTenantId = "1";
|
||||||
|
|
||||||
/** 共享服务列表(不区分租户,所有租户共用) */
|
/** 共享服务列表(不区分租户,所有租户共用) */
|
||||||
private List<String> sharedServices = Arrays.asList(
|
private List<String> sharedServices = Arrays.asList(
|
||||||
"fund-gateway",
|
"fund-gateway",
|
||||||
@ -28,10 +49,10 @@ public class TenantRoutingProperties {
|
|||||||
"fund-file"
|
"fund-file"
|
||||||
);
|
);
|
||||||
|
|
||||||
/** 默认租户 ID(当未指定时使用) */
|
|
||||||
private String defaultTenantId = "1";
|
|
||||||
|
|
||||||
/** 租户服务配置映射 */
|
/** 租户服务配置映射 */
|
||||||
|
private Map<String, TenantServiceConfig> services = new HashMap<>();
|
||||||
|
|
||||||
|
/** 租户服务配置(旧版兼容) */
|
||||||
private Map<String, TenantServiceConfig> tenantConfigs = new HashMap<>();
|
private Map<String, TenantServiceConfig> tenantConfigs = new HashMap<>();
|
||||||
|
|
||||||
// Getters and Setters
|
// Getters and Setters
|
||||||
@ -68,6 +89,14 @@ public class TenantRoutingProperties {
|
|||||||
this.groupSeparator = groupSeparator;
|
this.groupSeparator = groupSeparator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDefaultTenantId() {
|
||||||
|
return defaultTenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefaultTenantId(String defaultTenantId) {
|
||||||
|
this.defaultTenantId = defaultTenantId;
|
||||||
|
}
|
||||||
|
|
||||||
public List<String> getSharedServices() {
|
public List<String> getSharedServices() {
|
||||||
return sharedServices;
|
return sharedServices;
|
||||||
}
|
}
|
||||||
@ -76,12 +105,12 @@ public class TenantRoutingProperties {
|
|||||||
this.sharedServices = sharedServices;
|
this.sharedServices = sharedServices;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDefaultTenantId() {
|
public Map<String, TenantServiceConfig> getServices() {
|
||||||
return defaultTenantId;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDefaultTenantId(String defaultTenantId) {
|
public void setServices(Map<String, TenantServiceConfig> services) {
|
||||||
this.defaultTenantId = defaultTenantId;
|
this.services = services;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, TenantServiceConfig> getTenantConfigs() {
|
public Map<String, TenantServiceConfig> getTenantConfigs() {
|
||||||
@ -109,21 +138,76 @@ public class TenantRoutingProperties {
|
|||||||
return sharedServices.contains(serviceName);
|
return sharedServices.contains(serviceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取服务的 VIP 租户列表
|
||||||
|
*/
|
||||||
|
public List<String> getVipTenants(String serviceName) {
|
||||||
|
TenantServiceConfig config = services.get(serviceName);
|
||||||
|
if (config != null && config.getVipTenants() != null) {
|
||||||
|
return config.getVipTenants();
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断租户是否为某个服务的 VIP 租户
|
||||||
|
*/
|
||||||
|
public boolean isVipTenant(String serviceName, String tenantGroup) {
|
||||||
|
if (tenantGroup == null || tenantGroup.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
List<String> vipTenants = getVipTenants(serviceName);
|
||||||
|
return vipTenants.contains(tenantGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断服务是否启用了共享实例回退
|
||||||
|
*/
|
||||||
|
public boolean isFallbackToShared(String serviceName) {
|
||||||
|
TenantServiceConfig config = services.get(serviceName);
|
||||||
|
if (config != null) {
|
||||||
|
return config.isFallbackToShared();
|
||||||
|
}
|
||||||
|
return true; // 默认启用回退
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 租户服务配置
|
* 租户服务配置
|
||||||
*/
|
*/
|
||||||
public static class TenantServiceConfig {
|
public static class TenantServiceConfig {
|
||||||
|
/** VIP 租户列表(优先路由到专属实例) */
|
||||||
|
private List<String> vipTenants = new ArrayList<>();
|
||||||
|
|
||||||
|
/** 是否回退到共享实例 */
|
||||||
|
private boolean fallbackToShared = true;
|
||||||
|
|
||||||
/** 租户 ID */
|
/** 租户 ID */
|
||||||
private String tenantId;
|
private String tenantId;
|
||||||
|
|
||||||
/** 服务实例配置 */
|
/** 服务实例配置 */
|
||||||
private Map<String, ServiceInstanceConfig> services = new HashMap<>();
|
private Map<String, ServiceInstanceConfig> instances = new HashMap<>();
|
||||||
|
|
||||||
/** 数据库配置(一库一租户模式) */
|
/** 数据库配置(一库一租户模式) */
|
||||||
private DatabaseConfig database;
|
private DatabaseConfig database;
|
||||||
|
|
||||||
// Getters and Setters
|
// Getters and Setters
|
||||||
|
|
||||||
|
public List<String> getVipTenants() {
|
||||||
|
return vipTenants;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVipTenants(List<String> vipTenants) {
|
||||||
|
this.vipTenants = vipTenants != null ? vipTenants : new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFallbackToShared() {
|
||||||
|
return fallbackToShared;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFallbackToShared(boolean fallbackToShared) {
|
||||||
|
this.fallbackToShared = fallbackToShared;
|
||||||
|
}
|
||||||
|
|
||||||
public String getTenantId() {
|
public String getTenantId() {
|
||||||
return tenantId;
|
return tenantId;
|
||||||
}
|
}
|
||||||
@ -132,12 +216,12 @@ public class TenantRoutingProperties {
|
|||||||
this.tenantId = tenantId;
|
this.tenantId = tenantId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, ServiceInstanceConfig> getServices() {
|
public Map<String, ServiceInstanceConfig> getInstances() {
|
||||||
return services;
|
return instances;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setServices(Map<String, ServiceInstanceConfig> services) {
|
public void setInstances(Map<String, ServiceInstanceConfig> instances) {
|
||||||
this.services = services;
|
this.instances = instances;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DatabaseConfig getDatabase() {
|
public DatabaseConfig getDatabase() {
|
||||||
|
|||||||
@ -17,12 +17,22 @@ spring:
|
|||||||
namespace: ${NACOS_NAMESPACE:}
|
namespace: ${NACOS_NAMESPACE:}
|
||||||
group: DEFAULT_GROUP
|
group: DEFAULT_GROUP
|
||||||
enabled: true
|
enabled: true
|
||||||
|
metadata:
|
||||||
|
service-type: gateway
|
||||||
|
|
||||||
gateway:
|
gateway:
|
||||||
discovery:
|
discovery:
|
||||||
locator:
|
locator:
|
||||||
enabled: true
|
enabled: true
|
||||||
lower-case-service-id: true
|
lower-case-service-id: true
|
||||||
|
# 全局跨域配置
|
||||||
|
globalcors:
|
||||||
|
cors-configurations:
|
||||||
|
'[/**]':
|
||||||
|
allowed-origins: "*"
|
||||||
|
allowed-methods: "*"
|
||||||
|
allowed-headers: "*"
|
||||||
|
allow-credentials: true
|
||||||
routes:
|
routes:
|
||||||
- id: fund-sys
|
- id: fund-sys
|
||||||
uri: lb://fund-sys
|
uri: lb://fund-sys
|
||||||
@ -30,6 +40,7 @@ spring:
|
|||||||
- Path=/api/sys/**
|
- Path=/api/sys/**
|
||||||
filters:
|
filters:
|
||||||
- StripPrefix=1
|
- StripPrefix=1
|
||||||
|
# 租户感知负载均衡(自动添加 tenant-group 请求头)
|
||||||
- id: fund-cust
|
- id: fund-cust
|
||||||
uri: lb://fund-cust
|
uri: lb://fund-cust
|
||||||
predicates:
|
predicates:
|
||||||
@ -75,8 +86,46 @@ spring:
|
|||||||
|
|
||||||
# JWT 配置
|
# JWT 配置
|
||||||
jwt:
|
jwt:
|
||||||
secret: YourSecretKeyForJWTTokenGenerationMustBeAtLeast256BitsLong
|
secret: ${JWT_SECRET:YourSecretKeyForJWTTokenGenerationMustBeAtLeast256BitsLong}
|
||||||
expiration: 86400000
|
expiration: ${JWT_EXPIRATION:86400000}
|
||||||
|
|
||||||
|
# ==================== 多租户混合模式配置 ====================
|
||||||
|
tenant:
|
||||||
|
routing:
|
||||||
|
# 启用租户感知负载均衡
|
||||||
|
enabled: true
|
||||||
|
# 默认租户ID
|
||||||
|
default-tenant-id: 1
|
||||||
|
# 租户服务配置(定义每个服务的VIP租户)
|
||||||
|
services:
|
||||||
|
fund-sys:
|
||||||
|
vip-tenants:
|
||||||
|
- TENANT_VIP_001
|
||||||
|
- TENANT_VIP_002
|
||||||
|
fallback-to-shared: true
|
||||||
|
fund-cust:
|
||||||
|
vip-tenants:
|
||||||
|
- TENANT_VIP_001
|
||||||
|
fallback-to-shared: true
|
||||||
|
fund-proj:
|
||||||
|
vip-tenants:
|
||||||
|
- TENANT_VIP_001
|
||||||
|
fallback-to-shared: true
|
||||||
|
fund-req:
|
||||||
|
vip-tenants: []
|
||||||
|
fallback-to-shared: true
|
||||||
|
fund-exp:
|
||||||
|
vip-tenants: []
|
||||||
|
fallback-to-shared: true
|
||||||
|
fund-receipt:
|
||||||
|
vip-tenants: []
|
||||||
|
fallback-to-shared: true
|
||||||
|
fund-report:
|
||||||
|
vip-tenants: []
|
||||||
|
fallback-to-shared: true
|
||||||
|
fund-file:
|
||||||
|
vip-tenants: []
|
||||||
|
fallback-to-shared: true
|
||||||
|
|
||||||
# Actuator 监控端点配置
|
# Actuator 监控端点配置
|
||||||
management:
|
management:
|
||||||
@ -98,6 +147,7 @@ management:
|
|||||||
metrics:
|
metrics:
|
||||||
tags:
|
tags:
|
||||||
application: ${spring.application.name}
|
application: ${spring.application.name}
|
||||||
|
service-type: gateway
|
||||||
distribution:
|
distribution:
|
||||||
percentiles-histogram:
|
percentiles-histogram:
|
||||||
http.server.requests: true
|
http.server.requests: true
|
||||||
@ -109,5 +159,8 @@ logging:
|
|||||||
level:
|
level:
|
||||||
root: INFO
|
root: INFO
|
||||||
com.fundplatform: DEBUG
|
com.fundplatform: DEBUG
|
||||||
|
# 多租户负载均衡日志
|
||||||
|
com.fundplatform.common.loadbalancer: DEBUG
|
||||||
|
com.fundplatform.gateway.filter: DEBUG
|
||||||
pattern:
|
pattern:
|
||||||
console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] %-5level %logger{36} - %msg%n"
|
console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%X{tenantId}] %-5level %logger{36} - %msg%n"
|
||||||
|
|||||||
@ -38,6 +38,12 @@ spring:
|
|||||||
namespace: ${NACOS_NAMESPACE:}
|
namespace: ${NACOS_NAMESPACE:}
|
||||||
group: DEFAULT_GROUP
|
group: DEFAULT_GROUP
|
||||||
enabled: true
|
enabled: true
|
||||||
|
# 多租户元数据配置(支持混合模式负载均衡)
|
||||||
|
metadata:
|
||||||
|
tenant-id: ${TENANT_ID:1}
|
||||||
|
tenant-group: ${TENANT_GROUP:}
|
||||||
|
# 服务实例权重(VIP实例可配置更高权重)
|
||||||
|
weight: ${NACOS_WEIGHT:1}
|
||||||
|
|
||||||
# MyBatis Plus 配置
|
# MyBatis Plus 配置
|
||||||
mybatis-plus:
|
mybatis-plus:
|
||||||
@ -49,6 +55,31 @@ mybatis-plus:
|
|||||||
logic-delete-value: 1
|
logic-delete-value: 1
|
||||||
logic-not-delete-value: 0
|
logic-not-delete-value: 0
|
||||||
|
|
||||||
|
# ==================== 多租户混合模式配置 ====================
|
||||||
|
tenant:
|
||||||
|
routing:
|
||||||
|
# 启用租户感知负载均衡
|
||||||
|
enabled: true
|
||||||
|
# 默认租户ID
|
||||||
|
default-tenant-id: 1
|
||||||
|
# 租户服务配置
|
||||||
|
services:
|
||||||
|
fund-sys:
|
||||||
|
# VIP租户列表(优先路由到专属实例)
|
||||||
|
vip-tenants:
|
||||||
|
- TENANT_VIP_001
|
||||||
|
- TENANT_VIP_002
|
||||||
|
# 共享实例回退策略:当无专属实例时回退到共享实例
|
||||||
|
fallback-to-shared: true
|
||||||
|
fund-cust:
|
||||||
|
vip-tenants:
|
||||||
|
- TENANT_VIP_001
|
||||||
|
fallback-to-shared: true
|
||||||
|
fund-proj:
|
||||||
|
vip-tenants:
|
||||||
|
- TENANT_VIP_001
|
||||||
|
fallback-to-shared: true
|
||||||
|
|
||||||
# Actuator 监控端点配置
|
# Actuator 监控端点配置
|
||||||
management:
|
management:
|
||||||
endpoints:
|
endpoints:
|
||||||
@ -69,6 +100,10 @@ management:
|
|||||||
metrics:
|
metrics:
|
||||||
tags:
|
tags:
|
||||||
application: ${spring.application.name}
|
application: ${spring.application.name}
|
||||||
|
# 多租户监控标签
|
||||||
|
tenant_id: ${TENANT_ID:1}
|
||||||
|
tenant_group: ${TENANT_GROUP:shared}
|
||||||
|
instance_type: ${TENANT_GROUP:shared}
|
||||||
distribution:
|
distribution:
|
||||||
percentiles-histogram:
|
percentiles-histogram:
|
||||||
http.server.requests: true
|
http.server.requests: true
|
||||||
@ -80,5 +115,8 @@ logging:
|
|||||||
level:
|
level:
|
||||||
root: INFO
|
root: INFO
|
||||||
com.fundplatform: DEBUG
|
com.fundplatform: DEBUG
|
||||||
|
# 多租户负载均衡日志
|
||||||
|
com.fundplatform.common.loadbalancer: DEBUG
|
||||||
|
com.fundplatform.common.nacos: DEBUG
|
||||||
pattern:
|
pattern:
|
||||||
console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] %-5level %logger{36} - %msg%n"
|
console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] [%X{tenantId}] %-5level %logger{36} - %msg%n"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user