spring-boot-starters/wx-java-miniapp-multi-spring-boot-starter/MULTI_TENANT_MODE.md
从 4.8.0 版本开始,wx-java-miniapp-multi-spring-boot-starter 支持两种多租户实现模式:
每个租户创建独立的 WxMaService 实例,各自拥有独立的 HTTP 客户端。
优点:
缺点:
适用场景:
使用单个 WxMaService 实例管理所有租户配置,所有租户共享同一个 HTTP 客户端。
优点:
缺点:
适用场景:
wx:
ma:
# 多租户配置
apps:
tenant1:
app-id: wxd898fcb01713c555
app-secret: 47a2422a5d04a27e2b3ed1f1f0b0dbad
token: aBcDeFg123456
aes-key: abcdefgh123456abcdefgh123456abc
tenant2:
app-id: wx1234567890abcdef
app-secret: 1234567890abcdef1234567890abcdef
token: token123
aes-key: aeskey123aeskey123aeskey123aes
# 配置存储(可选)
config-storage:
type: memory # memory, jedis, redisson, redis_template
http-client-type: http_client # http_client, ok_http, jodd_http
# multi-tenant-mode: isolated # 默认值,可以不配置
wx:
ma:
# 多租户配置
apps:
tenant1:
app-id: wxd898fcb01713c555
app-secret: 47a2422a5d04a27e2b3ed1f1f0b0dbad
tenant2:
app-id: wx1234567890abcdef
app-secret: 1234567890abcdef1234567890abcdef
# ... 可配置更多租户
# 配置存储
config-storage:
type: memory
http-client-type: http_client
multi-tenant-mode: shared # 启用共享模式
两种模式下的代码使用方式完全相同:
@RestController
@RequestMapping("/ma")
public class MiniAppController {
@Autowired
private WxMaMultiServices wxMaMultiServices;
@GetMapping("/userInfo/{tenantId}")
public String getUserInfo(@PathVariable String tenantId, @RequestParam String code) {
// 获取指定租户的 WxMaService
WxMaService wxMaService = wxMaMultiServices.getWxMaService(tenantId);
try {
WxMaJscode2SessionResult session = wxMaService.jsCode2SessionInfo(code);
return "OpenId: " + session.getOpenid();
} catch (WxErrorException e) {
return "错误: " + e.getMessage();
}
}
}
以 100 个租户为例:
| 指标 | 隔离模式 | 共享模式 |
|---|---|---|
| HTTP 客户端数量 | 100 个 | 1 个 |
| 内存占用(估算) | ~500MB | ~50MB |
| 线程安全 | ✅ 完全安全 | ⚠️ 需注意异步场景 |
| 性能 | 略高(无 ThreadLocal 切换) | 略低(有 ThreadLocal 切换) |
| 适用场景 | 中小规模 | 大规模 |
如果使用共享模式,在异步编程时需要注意 ThreadLocal 的传递:
@Service
public class MiniAppService {
@Autowired
private WxMaMultiServices wxMaMultiServices;
public void asyncOperation(String tenantId) {
WxMaService wxMaService = wxMaMultiServices.getWxMaService(tenantId);
// ❌ 错误:异步线程无法获取到正确的配置
CompletableFuture.runAsync(() -> {
// 这里 wxMaService.getWxMaConfig() 可能返回错误的配置
wxMaService.getUserService().getUserInfo(...);
});
// ✅ 正确:在主线程获取配置,传递给异步线程
WxMaConfig config = wxMaService.getWxMaConfig();
String appId = config.getAppid();
CompletableFuture.runAsync(() -> {
// 使用已获取的配置信息
log.info("AppId: {}", appId);
});
}
}
两种模式都支持运行时动态添加或删除租户配置。
如果您正在使用旧版本,升级到 4.8.0+ 后:
multi-tenant-mode,将继续使用隔离模式(与旧版本行为一致)multi-tenant-mode: shared 启用共享模式issue讨论地址:#3835
基础实现类的 configMap:
BaseWxMaServiceImplSpring Boot Starter 的 services Map:
WxMaMultiServicesImpl新版本通过配置项让用户自主选择实现方式:
用户 → WxMaMultiServices 接口
↓
┌────┴────┐
↓ ↓
隔离模式 共享模式
(多Service) (单Service+configMap)
这样既保留了线程安全的优势(隔离模式),又提供了资源节省的选项(共享模式)。