一、多租戶的基本概念
多租戶(Multi-Tenancy) 是指在一套軟件系統中,多個租戶(客戶)共享相同的基礎設施和應用程序,但數據和配置相互隔離的架構模式。其核心目標是 降低成本 和 保證數據安全。
核心特點:
- 資源共享:租戶共享服務器、數據庫、代碼等資源。
- 數據隔離:通過技術手段確保租戶間數據不泄露。
- 配置獨立:支持租戶自定義配置(如界面、流程)。
隔離級別:
- 行級隔離:同一表中通過
tenant_id
字段區分(共享Schema模式)。 - Schema級隔離:同一數據庫下不同Schema(共享數據庫獨立Schema模式)。
- 數據庫級隔離:每個租戶獨立數據庫(獨立數據庫模式)。
二、Spring Cloud集成MyBatis-Plus實現多租戶
Spring Cloud與MyBatis-Plus結合實現多租戶,需解決 租戶ID傳遞、SQL自動過濾、數據填充 三個核心問題。
1. 核心組件集成
- API網關(Spring Cloud Gateway):從請求頭/Token中提取租戶ID,并向下游傳遞。
- 上下文傳遞:通過
ThreadLocal
在微服務間傳遞租戶ID。 - MyBatis-Plus插件:自動在SQL中注入租戶過濾條件。
- Feign客戶端:跨服務調用時傳遞租戶ID到請求頭。
2. 租戶ID全鏈路傳遞實現
(1)Spring Cloud Gateway過濾器(JwtTenantFilter)
通過GlobalFilter
解析JWT并將租戶ID存入上下文:
@Component
public class JwtTenantFilter implements GlobalFilter, Ordered {private final JwtUtils jwtUtils;public JwtTenantFilter(JwtUtils jwtUtils) {this.jwtUtils = jwtUtils;}@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 1. 從請求頭獲取JWT(格式:Bearer {token})String authHeader = exchange.getRequest().getHeaders().getFirst("Authorization");if (authHeader == null || !authHeader.startsWith("Bearer ")) {return handleMissingToken(exchange);}String token = authHeader.substring(7);try {// 2. 解析JWT獲取tenantIDString tenantId = jwtUtils.getTenantIdFromToken(token);if (tenantId == null) {return handleInvalidTenant(exchange);}// 3. 將tenantID存入上下文(關鍵點!)TenantContextHolder.setTenantId(tenantId);// 4. 添加X-Tenant-ID到請求頭,傳遞給下游服務ServerHttpRequest newRequest = exchange.getRequest().mutate().header("X-Tenant-ID", tenantId).build();// 5. 請求結束后清除上下文,防止內存泄漏return chain.filter(exchange.mutate().request(newRequest).build()).doFinally(signal -> TenantContextHolder.clear());} catch (JwtValidationException e) {return handleJwtError(exchange, e);}}