多租户
介绍
多租户指的是多用户在共用同一个环境时仍可以确保数据的隔离性。
隔离方案具体可以分三种:逻辑隔离、物理隔离、逻辑和物理混用
逻辑隔离
介绍
逻辑隔离指的是,在业务表中通过租户ID字段的数据来区分不同的租户。
架构层会在执行insert时自动将租户ID的参数进行赋值,在执行select、update和delete时自动拼接租户ID条件。 (租户Id的数据来源于TenantContextHolder)
开发人员可通过配置文件来排除不需要进行隔离的数据表,并配置租户ID字段名称(默认为tenant_id)
使用方式:
- 自己工程的POM文件里导入以下配置
<!--多租户动态数据源支持逻辑隔离-->
<dependency>
<groupId>com.sofast.cloud</groupId>
<artifactId>so-fast-web-tenant-starter</artifactId>
</dependency>
- 所需多租户服务中需如下配置
#tenant配置
sofast:
tenant:
#是否启用
enable: true
#租户ID字段名
column: tenant_id
#忽略的表名
ignore: sys_dict_data,sys_dict_type,sys_settings_parameter, sys_tenant
物理隔离
so-fast框架支持平台级的多租户功能数据库隔离
组件介绍:
框架基于dynamic-datasource-spring-boot-starter组件来实现的多租户的动态数据源切换功能。
dynamic-datasource-spring-boot-starter 是一个基于springboot的快速集成多数据源的启动器。
源码地址-github: https://github.com/baomidou/dynamic-datasource-spring-boot-starter
实现原理:
在租户创建时执行内置的SQL脚本生成对应的数据库,表和初始数据,并以SoFast_tenant_DS:租户ID:服务名:版本为KEY将相应的数据源信息缓存在redis中。
当租户请求对应的服务时,通过Filter拦截请求,并根据请求头里的tenantId来切换租户的数据源,保证同一个服务支持多数据库的租户模式。
根据请求头里的租户ID获取缓存中对应的数据源列表,创建或切换对应的数据源,并根据数据源切换策略将其设定其为当前的数据源。
请求头中的tenantId是网关服务从Token中解析出的
对于白名单中的接口需要前端手动设置header中的tenantId
使用方式:
在不同的场景下可以选用不同的配置方式:
- 标准版: 单个业务服务中每个租户只使用一个数据源
- 读写分离版: 单个业务服务中一个写数据源,一个/多个读数据源
开发集成
在业务工程的POM文件中导入以下配置
<dependency>
<groupId>com.sofast.cloud</groupId>
<artifactId>so-fast-web-tenant-starter</artifactId>
<exclusions>
<!-- 去除多租户逻辑隔离 -->
<exclusion>
<groupId>com.sofast.cloud</groupId>
<artifactId>so-fast-mybatis-tenant-starter</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--Mybatis-plus-->
<dependency>
<groupId>com.sofast.cloud</groupId>
<artifactId>so-fast-mybatis-starter</artifactId>
</dependency>
<!--多租户动态数据源支持Schema隔离-->
<dependency>
<groupId>com.sofast.cloud</groupId>
<artifactId>so-fast-ds-tenant-starter</artifactId>
</dependency>
修改so-fast-tenant的配置文件,按照以下格式来配置多租户的服务
sofast:
tenant:
#是否启用
enable: true
#白名单
excludes: /login/**, /token/logout
#默认租户ID
defaultTenantId: sf
dstenants:
#利用tenant端点,多租户版本的数据库服务信息
services:
#服务名称
- serviceName: so-fast-uaa
#数据源schema(库名)
schemaName: sf-upms
#数据源切换策略(1:负载;2:随机)
dsSwitchingStrategy: 2
#数据源组名
dsGroupNames: master
- serviceName: so-fast-flowable
schemaName: sf-flowable
dsSwitchingStrategy: 2
dsGroupNames: master
- serviceName: so-fast-cms
schemaName: sf-cms
dsSwitchingStrategy: 2
dsGroupNames: master
- serviceName: so-fast-external-api
schemaName: sf-external-api
dsSwitchingStrategy: 2
dsGroupNames: master
- serviceName: so-fast-fs
schemaName: sf-system
dsSwitchingStrategy: 2
dsGroupNames: master
- serviceName: so-fast-log
schemaName: sf-log
dsSwitchingStrategy: 2
dsGroupNames: master,slave
- serviceName: so-fast-notice
schemaName: sf-system
dsSwitchingStrategy: 2
dsGroupNames: master
- serviceName: so-fast-system
schemaName: sf-system
dsSwitchingStrategy: 2
dsGroupNames: master
- serviceName: so-fast-upms
schemaName: sf-upms
dsSwitchingStrategy: 2
dsGroupNames: master
属性说明
- serviceName: 服务名称
- schemaName: 默认的该服务建库名称
- dsSwitchingStrategy: 当配置同组多个数据源的场景,作为数据源自动切换的策略
- dsGroupNames: 数据源组名称使用(多个值使用,分割)该值主要用于服务中存在多种数据源的场景,用于校验数据源创建
更新业务服务的初始化SQL脚本,位置在resources/template中,文件名以服务名称来命名。
so-fast-tenant工程只提供了基础的租户管理内容。如需进行业务绑定,自行创建关联表进行维护。
如需进行手动切换数据源,则可以使用 @TenantDS 注解进行切换,使用时可将该注解放在需要切换的方法上
注解属性说明:
- value: 数据池名称(多租户管理中配置的数据池名称)或数据源分组名称(多租户管理中配置的数据组名称)
- isPoolName: 是否数据池名称
使用注解主要适用于 读写分离 的业务场景
- 首先修改so-fast-tenant的配置文件,在sofast.dstenants.service中设置dsGroupNames(master:写库;slave:读库)
- 在租户管理中将 写库 设置为服务的 默认数据源
- 在编码时,对于较为复杂的查询方法上使用 @TenantDS 注解(可指定使用的 数据源组名称 或者指定对应的 数据源名称 )
// 当isPoolName = false时,value指的是数据源组名称(ds_group_name);
// 当isPoolName = true时,value指的是数据源名称(pool_name)
@TenantDS(value = "slave", isPoolName = flase)
页面功能介绍
登录页面
登录地址由 /login 变更为 /login/:tenantId
租户管理
用于维护租户信息
租户ID不可编辑 创建租户之后,会自动根据配置文件中的服务信息创建租户服务数据
租户服务列表
租户服务列表主要用于维护数据源的自动切换策略,并对服务进行发布。
服务发布之后会将当前的数据源管理中 可用的数据源配置数据 进行快照,并将数据同步到Redis中。
数据源管理
用于维护租户数据源信息
初始化数据之后无法再次初始化,为防止覆盖业务数据
当数据库创建方式为 自动创建 ,则数据源状态默认为 不可用 ,只有进行 数据初始化 成功之后,该数据源才会变为 可用 状态
当数据库创建方式为 手动创建 ,则需要人工初始化对应数据源的DB结构和数据,该数据源默认状态为 可用状态