本节目录
- 什么是多租户
- 在ABP中的多租户
- 启用多租户
- Host vs Tenant
- Session
- Data Filters
- IMustHaveTenant
- IMayHaveTenant
- 保存实体
什么是多租户
维基百科:软件多租户是1个软件架构,软件的1个实例跑在服务器上,并且为多个租户服务着.
1个租户是指软件中的公用1种特定权限的一群用户.
在多租户的架构下,软件可以为每个租户提供独立的数据,配置,用户管理.
与多实例架构相比,为通过分离软件实例提供给不同租户的操作.
多租户用于创建SaaS(Software as-a Service)应用(云计算).
有以下几种多租户:
多部署-多数据库
事实上,这不是多租户.如果我们在单台服务器上提供多租户服务,通过分离数据库,为每个租户提供1个软件实例.我们只需确保多个软件实例在同1个服务器中互不冲突.
已存在的应用几乎都能实现.很容易创建这样的应用,应用不需要关心多租户.
但是他们部署,使用和维护都是问题.
单部署-多数据库
在这种情况下,我们可以在服务器上运行1个软件的实例.每个用户登录的时候,我们从master数据库中检查用户的租户,然后获取对应的租户所在数据库信息(连接字符串).
然后我们存储连接字符串到session中,执行数据库操作的时候使用这个特定的连接字符串.
在这个情况下,软件需要设计成多租户的.对于多租户来说,软件大部分是独立的.
同样这种软件也存在安装,使用和部署的问题.我们需要为每个租户创建和部署数据库.
单部署-单数据库
这是最真实的多租户架构:我们部署软件的单个实例,部署单个数据库到一台服务器上.
我们会在需要做多租户的表中设计1个TenantId 字段.
这是容易部署和维护的.但是创建这样的软件比较难.
因为,我们需要阻止1个租户去读写其他租户的数据.我们为每次数据读操作可能需要添加1个TenantId filter.
同样的,如果这个实体和当前租户关联.我们在每次写的时候需要检查.这是非常无趣且容易出错的.
但是ABP会使用自动数据过滤帮助我们处理这些.
如果我们有多租户的大量数据,这种方法可能会有性能问题.我们可以分表或者为1组租户提供不同服务器.
在ABP中的多租户
ABP 提供了1个创建单部署,单数据库,多租户的架构框架支持.
启用多租户
多租户默认是禁用的.我们可以在PreInitialize 中启用.如下:
Configuration.MultiTenancy.IsEnabled = true;
Host vs Tenant
首先,我们说明多租户的2个条目.
- 租户:1个客户有他自己的用户,角色,权限,设置...以及完全独立其他租户使用这个软件.如果是1个CRM软件,不同的租户有他们自己的账户,联系人,产品和订单.所以,当我们说'多租户用户',我们指的是属于1个租户的用户.
- 租主:租主是唯一的.租主可以创建和管理租户.所以,一个'租主用户'是1个更高级别的,独立所有租户和管理他们.
Session
ABP定义了1个获取当前用户和租户的接口IAbpSession .这个接口在多租户下可以获取当前租户id.他会通过id过来数据.
- 如果UserId and TenantId都为null,当前用户未登录.所以,我们不知道当前用户角色.这种情况下,不会授权操作.
- 如果UserId is not null and TenantId is null,我们认为当前用户为host user.
- 如果UserId is not null and also TenantId is not null,我们认为当前用户tenant user.
(See session documentation for more information on the session.)
Data Filters
当从数据中查询实体,我们必须添加TenantId 获取当前tenant的数据.当你的实体,实现2个接口其中之一的时候,ABP会自动实现.(IMustHaveTenant and IMayHaveTenant)
IMustHaveTenant
这个接口通过TenantId 属性定义不同租户.
public class Product : Entity, IMustHaveTenant{ public int TenantId { get; set; } public string Name { get; set; } //...other properties}
这样,ABP就知道这是1个租户实体,会自动过滤tenant.
IMayHaveTenant
当我们需要在host和tenants共享实体时.即这个实体可能属于tenant或者是host.IMayHaveTenant 接口可以定义1个可空的TenantId.
public class Role : Entity, IMayHaveTenant{ public int? TenantId { get; set; } public string RoleName { get; set; } //...other properties}
以上例子中,我们用同1个Role类存储Host roles and Tenant roles.当TenantId 属性为null时,表示为host entity,不为null,表示这个实体属于指定的tenant.
IMayHaveTenant 不像IMustHaveTenant常用.比如:Product 类不能实现IMayHaveTenant 接口,当Product 类和实际软件需要相关,和tenants不不相关.
使用IMayHaveTenant 接口在host和tenant**享,会更难维护代码.
保存实体
1个租户用户无法创建和修改其他租户实体.
只要data filters开启,ABP会在保存数据前检查确认.(See data filters document for more information on data filters.)
原标题:[Architect] ABP(现代ASP.NET样板开发框架) 多租户
关键词:ASP.NET