1. 多租户微服务架构概述

多租户微服务分布式架构是现代企业级SaaS平台的核心架构模式,通过多租户隔离、微服务拆分、分布式部署实现高可用、高扩展、高安全的云服务平台。本文将详细介绍多租户架构设计、微服务拆分策略、分布式系统治理、服务发现与配置管理的完整解决方案。

1.1 核心功能

  1. 多租户架构: 租户隔离、数据隔离、资源隔离
  2. 微服务设计: 服务拆分、服务治理、服务监控
  3. 分布式系统: 服务发现、负载均衡、容错处理
  4. 服务治理: 配置管理、监控告警、链路追踪
  5. 架构演进: 从单体到微服务的演进策略

1.2 技术架构

1
2
3
4
5
用户请求 → 网关层 → 服务发现 → 微服务集群 → 数据存储
↓ ↓ ↓ ↓ ↓
多租户 → 租户识别 → 路由分发 → 服务调用 → 数据隔离
↓ ↓ ↓ ↓ ↓
SaaS平台 → 权限控制 → 负载均衡 → 容错处理 → 监控告警

2. 多租户架构配置

2.1 Maven依赖配置

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
<!-- pom.xml -->
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Spring Cloud Gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

<!-- Spring Cloud Netflix Eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

<!-- Spring Cloud Netflix Ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

<!-- Spring Cloud OpenFeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

<!-- Spring Cloud Config -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>

<!-- Spring Cloud Sleuth -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>

<!-- Spring Cloud Zipkin -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
</dependencies>

2.2 多租户架构配置类

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/**
* 多租户架构配置类
*/
@Configuration
public class MultiTenantConfig {

@Value("${multi-tenant.isolation-strategy:DATABASE}")
private String isolationStrategy;

@Value("${multi-tenant.default-tenant:default}")
private String defaultTenant;

@Value("${multi-tenant.header-name:X-Tenant-ID}")
private String tenantHeaderName;

/**
* 多租户配置属性
*/
@Bean
public MultiTenantProperties multiTenantProperties() {
return MultiTenantProperties.builder()
.isolationStrategy(isolationStrategy)
.defaultTenant(defaultTenant)
.tenantHeaderName(tenantHeaderName)
.build();
}

/**
* 租户上下文解析器
*/
@Bean
public TenantContextResolver tenantContextResolver() {
return new TenantContextResolver(multiTenantProperties());
}

/**
* 租户数据源路由
*/
@Bean
public TenantDataSourceRouter tenantDataSourceRouter() {
return new TenantDataSourceRouter(multiTenantProperties());
}

/**
* 租户拦截器
*/
@Bean
public TenantInterceptor tenantInterceptor() {
return new TenantInterceptor(tenantContextResolver());
}
}

/**
* 多租户配置属性
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MultiTenantProperties {
private String isolationStrategy; // DATABASE, SCHEMA, TABLE
private String defaultTenant;
private String tenantHeaderName;

// 数据隔离配置
private Map<String, DataSourceConfig> tenantDataSources = new HashMap<>();
private boolean enableDynamicDataSource = true;
private int maxTenantConnections = 100;

// 缓存配置
private boolean enableTenantCache = true;
private int tenantCacheExpireTime = 3600; // 秒
private String tenantCachePrefix = "tenant:";

// 安全配置
private boolean enableTenantSecurity = true;
private boolean enableCrossTenantAccess = false;
private List<String> allowedCrossTenantOperations = new ArrayList<>();
}

/**
* 数据源配置
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DataSourceConfig {
private String url;
private String username;
private String password;
private String driverClassName;
private int maxActive;
private int maxIdle;
private int minIdle;
private int initialSize;
}

3. 多租户上下文管理

3.1 租户上下文管理

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
/**
* 租户上下文
*/
public class TenantContext {
private static final ThreadLocal<String> TENANT_ID = new ThreadLocal<>();
private static final ThreadLocal<TenantInfo> TENANT_INFO = new ThreadLocal<>();

/**
* 设置租户ID
* @param tenantId 租户ID
*/
public static void setTenantId(String tenantId) {
TENANT_ID.set(tenantId);
}

/**
* 获取租户ID
* @return 租户ID
*/
public static String getTenantId() {
return TENANT_ID.get();
}

/**
* 设置租户信息
* @param tenantInfo 租户信息
*/
public static void setTenantInfo(TenantInfo tenantInfo) {
TENANT_INFO.set(tenantInfo);
}

/**
* 获取租户信息
* @return 租户信息
*/
public static TenantInfo getTenantInfo() {
return TENANT_INFO.get();
}

/**
* 清除租户上下文
*/
public static void clear() {
TENANT_ID.remove();
TENANT_INFO.remove();
}
}

/**
* 租户信息模型
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TenantInfo {
private String tenantId;
private String tenantName;
private String tenantCode;
private String status; // ACTIVE, INACTIVE, SUSPENDED
private String isolationStrategy;
private String databaseName;
private String schemaName;
private Map<String, Object> properties = new HashMap<>();
private LocalDateTime createTime;
private LocalDateTime updateTime;
}

/**
* 租户上下文解析器
*/
@Component
public class TenantContextResolver {

private final MultiTenantProperties properties;
private final TenantService tenantService;
private final RedisTemplate<String, Object> redisTemplate;

public TenantContextResolver(MultiTenantProperties properties) {
this.properties = properties;
this.tenantService = null; // 注入
this.redisTemplate = null; // 注入
}

/**
* 解析租户上下文
* @param request HTTP请求
* @return 租户信息
*/
public TenantInfo resolveTenantContext(HttpServletRequest request) {
try {
// 1. 从请求头获取租户ID
String tenantId = getTenantIdFromRequest(request);

// 2. 验证租户ID
if (tenantId == null || tenantId.isEmpty()) {
tenantId = properties.getDefaultTenant();
}

// 3. 获取租户信息
TenantInfo tenantInfo = getTenantInfo(tenantId);

// 4. 设置租户上下文
TenantContext.setTenantId(tenantId);
TenantContext.setTenantInfo(tenantInfo);

return tenantInfo;

} catch (Exception e) {
log.error("解析租户上下文失败", e);
return getDefaultTenantInfo();
}
}

/**
* 从请求中获取租户ID
* @param request HTTP请求
* @return 租户ID
*/
private String getTenantIdFromRequest(HttpServletRequest request) {
// 1. 从请求头获取
String tenantId = request.getHeader(properties.getTenantHeaderName());

// 2. 从请求参数获取
if (tenantId == null) {
tenantId = request.getParameter("tenantId");
}

// 3. 从JWT Token获取
if (tenantId == null) {
tenantId = getTenantIdFromToken(request);
}

return tenantId;
}

/**
* 从JWT Token获取租户ID
* @param request HTTP请求
* @return 租户ID
*/
private String getTenantIdFromToken(HttpServletRequest request) {
try {
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
token = token.substring(7);
// 解析JWT Token获取租户ID
// 这里需要实现JWT解析逻辑
return parseTenantIdFromToken(token);
}
} catch (Exception e) {
log.warn("从Token获取租户ID失败", e);
}
return null;
}

/**
* 获取租户信息
* @param tenantId 租户ID
* @return 租户信息
*/
private TenantInfo getTenantInfo(String tenantId) {
try {
// 1. 从缓存获取
if (properties.isEnableTenantCache()) {
TenantInfo cachedInfo = getTenantInfoFromCache(tenantId);
if (cachedInfo != null) {
return cachedInfo;
}
}

// 2. 从数据库获取
TenantInfo tenantInfo = tenantService.getTenantInfo(tenantId);

// 3. 缓存租户信息
if (tenantInfo != null && properties.isEnableTenantCache()) {
cacheTenantInfo(tenantId, tenantInfo);
}

return tenantInfo;

} catch (Exception e) {
log.error("获取租户信息失败: tenantId={}", tenantId, e);
return getDefaultTenantInfo();
}
}

/**
* 从缓存获取租户信息
* @param tenantId 租户ID
* @return 租户信息
*/
private TenantInfo getTenantInfoFromCache(String tenantId) {
try {
String cacheKey = properties.getTenantCachePrefix() + tenantId;
return (TenantInfo) redisTemplate.opsForValue().get(cacheKey);
} catch (Exception e) {
log.warn("从缓存获取租户信息失败: tenantId={}", tenantId, e);
return null;
}
}

/**
* 缓存租户信息
* @param tenantId 租户ID
* @param tenantInfo 租户信息
*/
private void cacheTenantInfo(String tenantId, TenantInfo tenantInfo) {
try {
String cacheKey = properties.getTenantCachePrefix() + tenantId;
redisTemplate.opsForValue().set(cacheKey, tenantInfo,
Duration.ofSeconds(properties.getTenantCacheExpireTime()));
} catch (Exception e) {
log.warn("缓存租户信息失败: tenantId={}", tenantId, e);
}
}

/**
* 获取默认租户信息
* @return 默认租户信息
*/
private TenantInfo getDefaultTenantInfo() {
return TenantInfo.builder()
.tenantId(properties.getDefaultTenant())
.tenantName("Default Tenant")
.tenantCode("default")
.status("ACTIVE")
.isolationStrategy(properties.getIsolationStrategy())
.build();
}

/**
* 解析Token中的租户ID
* @param token JWT Token
* @return 租户ID
*/
private String parseTenantIdFromToken(String token) {
// 实现JWT Token解析逻辑
// 这里需要根据实际的JWT实现来解析
return null;
}
}

4. 多租户数据源路由

4.1 多租户数据源路由

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/**
* 多租户数据源路由
*/
@Component
public class TenantDataSourceRouter {

private final MultiTenantProperties properties;
private final Map<String, DataSource> dataSourceMap = new HashMap<>();
private final DataSource defaultDataSource;

public TenantDataSourceRouter(MultiTenantProperties properties) {
this.properties = properties;
this.defaultDataSource = createDefaultDataSource();
initializeTenantDataSources();
}

/**
* 获取租户数据源
* @param tenantId 租户ID
* @return 数据源
*/
public DataSource getTenantDataSource(String tenantId) {
try {
// 1. 获取租户信息
TenantInfo tenantInfo = TenantContext.getTenantInfo();
if (tenantInfo == null) {
return defaultDataSource;
}

// 2. 根据隔离策略获取数据源
switch (tenantInfo.getIsolationStrategy()) {
case "DATABASE":
return getDatabaseDataSource(tenantId);
case "SCHEMA":
return getSchemaDataSource(tenantId);
case "TABLE":
return getTableDataSource(tenantId);
default:
return defaultDataSource;
}

} catch (Exception e) {
log.error("获取租户数据源失败: tenantId={}", tenantId, e);
return defaultDataSource;
}
}

/**
* 获取数据库级数据源
* @param tenantId 租户ID
* @return 数据源
*/
private DataSource getDatabaseDataSource(String tenantId) {
String dataSourceKey = "tenant_" + tenantId;

if (dataSourceMap.containsKey(dataSourceKey)) {
return dataSourceMap.get(dataSourceKey);
}

// 创建新的数据源
DataSource dataSource = createTenantDataSource(tenantId);
dataSourceMap.put(dataSourceKey, dataSource);

return dataSource;
}

/**
* 获取Schema级数据源
* @param tenantId 租户ID
* @return 数据源
*/
private DataSource getSchemaDataSource(String tenantId) {
// Schema级隔离使用同一个数据库,不同的Schema
return defaultDataSource;
}

/**
* 获取表级数据源
* @param tenantId 租户ID
* @return 数据源
*/
private DataSource getTableDataSource(String tenantId) {
// 表级隔离使用同一个数据库,表名包含租户ID
return defaultDataSource;
}

/**
* 创建租户数据源
* @param tenantId 租户ID
* @return 数据源
*/
private DataSource createTenantDataSource(String tenantId) {
try {
DataSourceConfig config = properties.getTenantDataSources().get(tenantId);
if (config == null) {
config = getDefaultDataSourceConfig(tenantId);
}

HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setJdbcUrl(config.getUrl());
hikariConfig.setUsername(config.getUsername());
hikariConfig.setPassword(config.getPassword());
hikariConfig.setDriverClassName(config.getDriverClassName());
hikariConfig.setMaximumPoolSize(config.getMaxActive());
hikariConfig.setMinimumIdle(config.getMinIdle());
hikariConfig.setConnectionTimeout(30000);
hikariConfig.setIdleTimeout(600000);
hikariConfig.setMaxLifetime(1800000);

return new HikariDataSource(hikariConfig);

} catch (Exception e) {
log.error("创建租户数据源失败: tenantId={}", tenantId, e);
return defaultDataSource;
}
}

/**
* 创建默认数据源
* @return 默认数据源
*/
private DataSource createDefaultDataSource() {
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setJdbcUrl("jdbc:mysql://localhost:3306/default_tenant?useUnicode=true&characterEncoding=utf8");
hikariConfig.setUsername("root");
hikariConfig.setPassword("password");
hikariConfig.setDriverClassName("com.mysql.cj.jdbc.Driver");
hikariConfig.setMaximumPoolSize(20);
hikariConfig.setMinimumIdle(5);

return new HikariDataSource(hikariConfig);
}

/**
* 获取默认数据源配置
* @param tenantId 租户ID
* @return 数据源配置
*/
private DataSourceConfig getDefaultDataSourceConfig(String tenantId) {
return DataSourceConfig.builder()
.url("jdbc:mysql://localhost:3306/tenant_" + tenantId + "?useUnicode=true&characterEncoding=utf8")
.username("root")
.password("password")
.driverClassName("com.mysql.cj.jdbc.Driver")
.maxActive(20)
.maxIdle(10)
.minIdle(5)
.initialSize(5)
.build();
}

/**
* 初始化租户数据源
*/
private void initializeTenantDataSources() {
try {
for (Map.Entry<String, DataSourceConfig> entry : properties.getTenantDataSources().entrySet()) {
String tenantId = entry.getKey();
DataSourceConfig config = entry.getValue();

DataSource dataSource = createTenantDataSource(tenantId);
dataSourceMap.put("tenant_" + tenantId, dataSource);

log.info("初始化租户数据源成功: tenantId={}", tenantId);
}
} catch (Exception e) {
log.error("初始化租户数据源失败", e);
}
}
}

5. 微服务架构设计

5.1 微服务架构设计

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/**
* 微服务架构配置
*/
@Configuration
public class MicroserviceArchitectureConfig {

@Value("${microservice.service-name}")
private String serviceName;

@Value("${microservice.version}")
private String version;

@Value("${microservice.port}")
private int port;

/**
* 微服务配置属性
*/
@Bean
public MicroserviceProperties microserviceProperties() {
return MicroserviceProperties.builder()
.serviceName(serviceName)
.version(version)
.port(port)
.build();
}

/**
* 服务注册配置
*/
@Bean
public ServiceRegistryConfig serviceRegistryConfig() {
return ServiceRegistryConfig.builder()
.enableServiceRegistry(true)
.registryUrl("http://localhost:8761")
.healthCheckUrl("/actuator/health")
.build();
}

/**
* 服务发现配置
*/
@Bean
public ServiceDiscoveryConfig serviceDiscoveryConfig() {
return ServiceDiscoveryConfig.builder()
.enableServiceDiscovery(true)
.discoveryUrl("http://localhost:8761")
.cacheRefreshInterval(30)
.build();
}
}

/**
* 微服务配置属性
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MicroserviceProperties {
private String serviceName;
private String version;
private int port;

// 服务治理配置
private boolean enableCircuitBreaker = true;
private boolean enableLoadBalancer = true;
private boolean enableRetry = true;
private int maxRetryAttempts = 3;

// 监控配置
private boolean enableMetrics = true;
private boolean enableTracing = true;
private String metricsEndpoint = "/actuator/metrics";
private String tracingEndpoint = "/actuator/trace";

// 安全配置
private boolean enableSecurity = true;
private String securityConfig = "default";
private boolean enableApiGateway = true;
}

/**
* 服务注册配置
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ServiceRegistryConfig {
private boolean enableServiceRegistry;
private String registryUrl;
private String healthCheckUrl;
private int heartbeatInterval = 30;
private int leaseRenewalInterval = 30;
private int leaseExpirationDuration = 90;
}

/**
* 服务发现配置
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ServiceDiscoveryConfig {
private boolean enableServiceDiscovery;
private String discoveryUrl;
private int cacheRefreshInterval;
private boolean enableHealthCheck = true;
private int healthCheckInterval = 30;
}

6. 服务治理与监控

6.1 服务治理与监控

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/**
* 服务治理配置
*/
@Configuration
public class ServiceGovernanceConfig {

/**
* 熔断器配置
*/
@Bean
public CircuitBreakerConfig circuitBreakerConfig() {
return CircuitBreakerConfig.builder()
.failureRateThreshold(50)
.waitDurationInOpenState(Duration.ofSeconds(30))
.slidingWindowSize(10)
.minimumNumberOfCalls(5)
.build();
}

/**
* 重试配置
*/
@Bean
public RetryConfig retryConfig() {
return RetryConfig.builder()
.maxAttempts(3)
.waitDuration(Duration.ofSeconds(1))
.retryOnException(throwable -> true)
.build();
}

/**
* 限流配置
*/
@Bean
public RateLimiterConfig rateLimiterConfig() {
return RateLimiterConfig.builder()
.limitForPeriod(100)
.limitRefreshPeriod(Duration.ofSeconds(1))
.timeoutDuration(Duration.ofSeconds(1))
.build();
}
}

/**
* 服务监控配置
*/
@Configuration
public class ServiceMonitoringConfig {

/**
* 指标收集器
*/
@Bean
public MeterRegistry meterRegistry() {
return new SimpleMeterRegistry();
}

/**
* 链路追踪配置
*/
@Bean
public TracingConfig tracingConfig() {
return TracingConfig.builder()
.serviceName("multi-tenant-service")
.samplingRate(1.0)
.zipkinEndpoint("http://localhost:9411/api/v2/spans")
.build();
}

/**
* 健康检查配置
*/
@Bean
public HealthIndicator healthIndicator() {
return new MultiTenantHealthIndicator();
}
}

/**
* 多租户健康检查
*/
@Component
public class MultiTenantHealthIndicator implements HealthIndicator {

private final TenantService tenantService;
private final TenantDataSourceRouter dataSourceRouter;

public MultiTenantHealthIndicator() {
this.tenantService = null; // 注入
this.dataSourceRouter = null; // 注入
}

@Override
public Health health() {
try {
// 检查租户服务状态
boolean tenantServiceHealthy = checkTenantService();

// 检查数据源状态
boolean dataSourceHealthy = checkDataSource();

if (tenantServiceHealthy && dataSourceHealthy) {
return Health.up()
.withDetail("tenantService", "UP")
.withDetail("dataSource", "UP")
.build();
} else {
return Health.down()
.withDetail("tenantService", tenantServiceHealthy ? "UP" : "DOWN")
.withDetail("dataSource", dataSourceHealthy ? "UP" : "DOWN")
.build();
}

} catch (Exception e) {
return Health.down()
.withDetail("error", e.getMessage())
.build();
}
}

/**
* 检查租户服务状态
* @return 是否健康
*/
private boolean checkTenantService() {
try {
// 实现租户服务健康检查逻辑
return true;
} catch (Exception e) {
log.error("租户服务健康检查失败", e);
return false;
}
}

/**
* 检查数据源状态
* @return 是否健康
*/
private boolean checkDataSource() {
try {
// 实现数据源健康检查逻辑
return true;
} catch (Exception e) {
log.error("数据源健康检查失败", e);
return false;
}
}
}

7. 多租户微服务控制器

7.1 多租户微服务控制器

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/**
* 多租户微服务控制器
*/
@RestController
@RequestMapping("/api/v1")
public class MultiTenantController {

@Autowired
private TenantService tenantService;

@Autowired
private TenantContextResolver tenantContextResolver;

/**
* 获取租户信息
*/
@GetMapping("/tenant/info")
public ResponseEntity<Map<String, Object>> getTenantInfo() {
try {
TenantInfo tenantInfo = TenantContext.getTenantInfo();

Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("tenantInfo", tenantInfo);

return ResponseEntity.ok(response);

} catch (Exception e) {
log.error("获取租户信息失败", e);

Map<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("message", "获取租户信息失败: " + e.getMessage());

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}

/**
* 切换租户
*/
@PostMapping("/tenant/switch")
public ResponseEntity<Map<String, Object>> switchTenant(@RequestParam String tenantId) {
try {
// 验证租户ID
if (tenantId == null || tenantId.isEmpty()) {
Map<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("message", "租户ID不能为空");
return ResponseEntity.badRequest().body(response);
}

// 获取租户信息
TenantInfo tenantInfo = tenantService.getTenantInfo(tenantId);
if (tenantInfo == null) {
Map<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("message", "租户不存在");
return ResponseEntity.badRequest().body(response);
}

// 设置租户上下文
TenantContext.setTenantId(tenantId);
TenantContext.setTenantInfo(tenantInfo);

Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("message", "租户切换成功");
response.put("tenantInfo", tenantInfo);

return ResponseEntity.ok(response);

} catch (Exception e) {
log.error("切换租户失败: tenantId={}", tenantId, e);

Map<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("message", "切换租户失败: " + e.getMessage());

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}

/**
* 获取服务状态
*/
@GetMapping("/service/status")
public ResponseEntity<Map<String, Object>> getServiceStatus() {
try {
Map<String, Object> status = new HashMap<>();
status.put("serviceName", "multi-tenant-service");
status.put("version", "1.0.0");
status.put("status", "UP");
status.put("timestamp", LocalDateTime.now());
status.put("tenantId", TenantContext.getTenantId());

Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("status", status);

return ResponseEntity.ok(response);

} catch (Exception e) {
log.error("获取服务状态失败", e);

Map<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("message", "获取服务状态失败: " + e.getMessage());

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}
}

8. 总结

通过多租户微服务分布式架构设计的实现,我们成功构建了一个企业级SaaS平台架构。关键特性包括:

8.1 核心优势

  1. 多租户架构: 租户隔离、数据隔离、资源隔离
  2. 微服务设计: 服务拆分、服务治理、服务监控
  3. 分布式系统: 服务发现、负载均衡、容错处理
  4. 服务治理: 配置管理、监控告警、链路追踪
  5. 架构演进: 从单体到微服务的演进策略

8.2 最佳实践

  1. 多租户隔离: 数据库级、Schema级、表级隔离策略
  2. 微服务拆分: 按业务域拆分、服务边界清晰
  3. 服务治理: 熔断、重试、限流、监控
  4. 分布式架构: 服务发现、配置中心、链路追踪
  5. 架构演进: 渐进式演进、风险控制

这套多租户微服务分布式架构方案不仅能够支持多租户SaaS平台,还包含了完整的微服务治理、分布式系统设计等核心功能,是企业级云服务平台的重要架构模式。