详解ABP框架的多租户
(此文章同时发表在本人微信公众号“dotNET每日精华文章”,欢迎右边二维码来关注。)
题记:ABP框架对多租户场景提供了很好的支持,内建了多租户的处理机制,今天我们来深入解析一下这一特性。
最近在基于ABP框架(ASP.NET Boilerplate)开发了一个SaaS。所以接下来可能会时不时分享一下ABP方面的文章。今天来介绍一下ABP对多租户提供的支持特性。
ABP简介
ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应用程序的新起点,它旨在成为一个通用的WEB应用程序框架和项目模板。ASP.NET Boilerplate 基于DDD的经典分层架构思想,实现了众多DDD的概念(但没有实现所有DDD的概念)。ABP不仅架构设计和代码写的好,文档也很全面详实(这是一个开发框架被技术选型的基础)。尤其国内的很多热心朋友还整理了中文的资料和文档,比如郭阳铭的系列文章(http://www.cnblogs.com/mienreal/p/4528470.html)和ABP框架中国小组的中文文档(https://github.com/ABPFrameWorkGroup/AbpDocument2Chinese)。
多租户
通常SaaS都是需要多租户支持的。维基百科对多租户的解释是:软件多租户是指一个软件架构的实例软件运行在一个服务器上,但存在多个租户。租户是一组共享一个公共的用户访问特定权限的软件实例。多租户架构,软件应用程序旨在提供每个租户专用的实例包括数据、配置、用户管理、租户个体功能和非功能属性。多租户与多实例架构,独立的软件实例代表不同的租户操作。
多租户一般涉及如下几种场景:
- 多部署-多数据库:即针对每个租户独立部署一套应用程序实例,每个实例对应一个数据库。这种不算是真正的多租户,不过对于在设计时没有考虑多租户的遗留系统采用这种部署方式不失为一种折中办法。
- 单部署-多数据库:只有唯一的一个应用程序实例,每个租户分别连接不同的数据库。
- 单部署-单数据库:应用程序实例和数据库都是一个。通过在需要隔离数据的数据表中加入一个类似TanantId或EnterpriseId来区分。
- 单部署-混搭数据库:应用程序实例一个,但是数据库根据情况,可以是单个或者多个。比如免费用户放到一个数据库中,高级用户分别有自己的数据库。
- 集群部署-单/多/混搭数据库:应用程序的逻辑实例还是一个(只是为了高可用和性能部署为一个集群),然后对应的数据库可以是单个、多个和混搭。
另外,除了针对租户的数据库以外,可能还需要一个全局的数据库(称之为主机数据库)来保存全局范围的配置数据。在单数据库情况下,主机数据可能就和租户数据放在一起(甚至同一个数据表中)。
ABP对多租户的支持
上面提到的所有多租户场景,在ABP都可以支持。只需要在启动配置中启用多租户即可。
Configuration.MultiTenancy.IsEnabled = true;
当然,最常见的场景恐怕就是单部署-单数据库,所以ABP中内置了处理TenantId的机制(通过接口IMustHaveTenant或IMayHaveTenant来实现)。实体实现了IMustHaveTenant接口,会包含一个不能为空的TenantId属性,即意味着其中的数据库需要基于TenantId来进行隔离。实现了IMayHaveTenant接口,会包含一个能为空的TenantId属性,在TenantId为空的时候代表数据属于主机范围的,不为空的时候表示数据基于租户来隔离。
而ABP通过一个特殊封装的IAbpSession来给使用者提供当前TenantId的获取,如果是主机用户登录系统,那么TenantId就是为空的,否则就是登录用户所在租户的Id。
ABP在多租户下读取数据
ABP并非只是简单的给你的实体类添加一个TenantId属性,而是通过识别IMustHaveTenant或IMayHaveTenant接口,使用数据过滤机制(根据底层所用ORM不同有不同的实现方式)自动在你读取数据的时候,基于当前AbpSession中的TenantId来过滤数据。也就是说,你查询读取数据的时候,写“where item.TenantId == AbpSession.TenantId” 这样的代码是毫无必要的。
需要注意的是,如果实体实现的是IMustHaveTenant接口,且AbpSession.TenantId为null的时候(即主机用户),获取到的数据是所有租户的,除非你自己显式进行过滤。而在IMayHaveTenant情况下,AbpSession.TenantId为null获取到的是主机用户的数据。
ABP在多租户下写入数据
在多租户的情形下,写入数据也通过拦截机制(比如重写DbContext的SaveChanges方法),可以自动为你的实体设置TenantId属性,不管你用的是IMustHaveTenant还是IMayHaveTenant。虽然官方文档是推荐在创建实体的时候,总是显示设置TenantId的,尤其在使用IMayHaveTenant的时候(这也是abp使用者唯一需要关系这个属性的地方)。但是,就我个人的看法而言,利用框架的原因就是为了让编码简单,所以我还是倾向于建议大家不用显式设置TenantId。
ABP切换租户
最后,ABP也提供一系列机制让你在代码中切换tenant(包括租户与主机间的切换)。关于多租户的官方文档(http://www.aspnetboilerplate.com/Pages/Documents/Multi-Tenancy)最后的内容也详细讲到了切换租户的一些最佳实践。
详解ABP框架的多租户的更多相关文章
- 详解Executor框架
在Java中,使用线程来异步执行任务.Java线程的创建与销毁需要一定的开销,如果我们为每一个任务创建一个新线程来执行,这些线程的创建与销毁将消耗大量的计算资源.同时,为每一个任务创建一个新线程来执行 ...
- 详解工作流框架Activiti的服务架构和组件
摘要:通过这篇文章,可以对工作流有一个基本的认识,为后续工作流框架Activiti的学习打下坚实的基础. 本文分享自华为云社区<BPMN工作流的基本概念!详解工作流框架Activiti的服务架构 ...
- [转载] 多图详解Spring框架的设计理念与设计模式
转载自http://developer.51cto.com/art/201006/205212_all.htm Spring作为现在最优秀的框架之一,已被广泛的使用,51CTO也曾经针对Spring框 ...
- JavaWeb配置详解(结合框架SpringMVC)
详解 先说一说常识性的东西,我们的JavaWeb程序运行一开始走的是web.xml文件,这是我们的核心文件,可以说没有web.xml文件我们就无法运行项目,这个文件长什么样子,读者自己新建一个web项 ...
- hadoop之yarn详解(框架进阶篇)
前面在hadoop之yarn详解(基础架构篇)这篇文章提到了yarn的重要组件有ResourceManager,NodeManager,ApplicationMaster等,以及yarn调度作业的运行 ...
- JAVA Eclipse使用Maven构建web项目详解(SSM框架)
tips: 启动项目后,welcome-file的链接即为测试用例 部署maven web项目 Eclipse使用Maven构建web项目详解 pom.xml添加webapp依赖: <depen ...
- 详解SSH框架的原理和优点
Struts的原理和优点. Struts工作原理 MVC即Model-View-Controller的缩写,是一种常用的设计模式.MVC 减弱了业务逻辑接口和数据接口之间的耦合,以及让 ...
- pycaffe︱caffe中fine-tuning模型三重天(函数详解、框架简述)
本文主要参考caffe官方文档[<Fine-tuning a Pretrained Network for Style Recognition>](http://nbviewer.jupy ...
- unittest----常用属性详解(框架属性详解)
很久没有写关于测试的随笔了,最近有空学习.整理一下关于unittest框架的知识. unittest单元测试框架,不仅可以适用于单元测试,还可以适用WEB自动化测试用例的开发与执行. unittest ...
随机推荐
- Python笔记(4)类__属性与描述符
部分参考自:http://www.geekfan.net/7862/ 新式类与经典类 2和3不一样,3都是新式类. 新式类和经典类的区别: class A: #classic class " ...
- 前端模块化工具-webpack
详解前端模块化工具-webpack webpack是一个module bundler,抛开博大精深的汉字问题,我们暂且管他叫'模块管理工具'.随着js能做的事情越来越多,浏览器.服务器,js似乎无处不 ...
- ArcGIS Server开发教程系列(1) Arcgis server 10.1 的安装
本系列所使用的软件版本如下: Windows 7 X64 / Windows server 2008 X64 Arcgis for Desktop 10.1 Arcgis 10.1 for serve ...
- ASP.NET中使用JqGrid完整实现
文章提纲 介绍 & 使用场景 JqGrid的一些说明 JqGrid和ASP.NET整合详细步骤 前置准备 框架搭建 数据填充 数据增/删/改 其他 介绍&使用场景 JqGrid不是一个 ...
- jQuery知识点一 each()和toggleClass()
jQuery的一些东东比较容易忘,所以在这里整理一下... ... 1. each (1) $(selector).each(function(index,element)) inde ...
- 2016-03-04记录 H264.TXT 转成 H264.h264
H264.TXT文件 来源于板子上串口输出的数据,需要把该数据转成 *.h264用 H264的软件打开观察 txt中数据截图如下: MATLAB读入数据的代码: clc;close all;clear ...
- PHP数组
PHP数组的遍历 使用for语句循环遍历数组 在PHP中,不仅可以指定非连续的数字索引值,而且还存在以字符串为下表的关联数组.所以在php中很少使用for语句循环来遍历数组.使用for语句遍历连续数字 ...
- phpcms v9图片生成缩略图变成黑色解决方法
今天客户反映,上传的图片生成缩略图有的图片变成黑色,出现问题就百度了一下,有不少网友也遇到这样的问题,但是官方论坛也没有给出解决办法,那还得靠自己解决了,于是就研究phpcms v9 图片压缩代码.打 ...
- [Data Structure & Algorithm] 八大排序算法
排序有内部排序和外部排序之分,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存.我们这里说的八大排序算法均为内部排序. 下图为排序 ...
- 支持向量机SVM
SVM(Support Vector Machine)有监督的机器学习方法,可以做分类也可以做回归.SVM把分类问题转化为寻找分类平面的问题,并通过最大化分类边界点距离分类平面的距离来实现分类. 有好 ...