1
0
mirror of synced 2026-02-04 16:40:54 +08:00
Files
WxJava/spring-boot-starters/wx-java-miniapp-multi-spring-boot-starter/MULTI_TENANT_MODE.md

5.7 KiB
Raw Blame History

微信小程序多租户配置说明

多租户模式对比

从 4.8.0 版本开始wx-java-miniapp-multi-spring-boot-starter 支持两种多租户实现模式:

1. 隔离模式ISOLATED默认

每个租户创建独立的 WxMaService 实例,各自拥有独立的 HTTP 客户端。

优点:

  • 线程安全,无需担心并发问题
  • 不依赖 ThreadLocal适合异步/响应式编程
  • 租户间完全隔离,互不影响

缺点:

  • 每个租户创建独立的 HTTP 客户端,资源占用较多
  • 适合租户数量不多的场景(建议 < 50 个租户)

适用场景:

  • SaaS 应用,租户数量较少
  • 异步编程、响应式编程场景
  • 对线程安全有严格要求

2. 共享模式SHARED

使用单个 WxMaService 实例管理所有租户配置,所有租户共享同一个 HTTP 客户端。

优点:

  • 共享 HTTP 客户端,大幅节省资源
  • 适合租户数量较多的场景(支持 100+ 租户)
  • 内存占用更小

缺点:

  • 依赖 ThreadLocal 切换配置,在异步场景需要特别注意
  • 需要注意线程上下文传递

适用场景:

  • 租户数量较多(> 50 个)
  • 同步编程场景
  • 对资源占用有严格要求

配置方式

使用隔离模式(默认)

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+ 后:

  1. 默认行为不变:如果不配置 multi-tenant-mode,将继续使用隔离模式(与旧版本行为一致)
  2. 向后兼容:所有现有代码无需修改
  3. 可选升级:如需节省资源,可配置 multi-tenant-mode: shared 启用共享模式

源码分析

issue讨论地址#3835

为什么有两种设计?

  1. 基础实现类的 configMap

    • 位置:BaseWxMaServiceImpl
    • 特点:单个 Service 实例 + 多个配置 + ThreadLocal 切换
    • 设计目的:支持在一个应用中管理多个小程序账号
  2. Spring Boot Starter 的 services Map

    • 位置:WxMaMultiServicesImpl
    • 特点:多个 Service 实例 + 每个实例一个配置
    • 设计目的:为 Spring Boot 提供更符合依赖注入风格的多租户支持

新版本改进

新版本通过配置项让用户自主选择实现方式:

用户 → WxMaMultiServices 接口
         ↓
    ┌────┴────┐
    ↓         ↓
隔离模式    共享模式
(多Service)  (单Service+configMap)

这样既保留了线程安全的优势(隔离模式),又提供了资源节省的选项(共享模式)。