说起多租户就不能不提起SaaS,SaaS对比传统软件概念而言规模效应非常强大。

运维成本、部署成本、开发投入等成本因素在传统的开发模式下都是陡峭的线性增长模型。

而SaaS模式下由于单一部署等特点,随着租户的数量的增加,规模效应逐渐明显,单个租户的成本明显下降。

那么多租户的设计就在SaaS系统中明显重要。在SaaS应用的成熟度模型中L1和L2只是过渡性的形态,真正的L3、L4才是SaaS的真正形态。由此可看出,真正的Saas一定是多租户的,可扩容的,便于配置的。

由于传统的设计实施方案中运维、开发成本都较高,基于这些问题,考虑使用容器化、虚拟化的手段来解决这些问题。

一、多租户设计

多租户设计需要考虑两个层面,一个是数据层,另一个是应用层。

1应用层面的设计

概念上,每个租户都要有自己专用的逻辑运行空间,并且在这部分空间托管了为租户单独提供服务的能力,另外主机用户还要有能力维护和管理租户的运行空间。

实际上,SaaS中使用一个运行时环境来为多个租户提供服务,不同租户之间存在多种多样的功能差异需要进行控制,同时也存在某些通用的功能。这些通用功能的开通、停用、配置等都要在环境中独立管理,并且互相隔离。

2数据层面的设计

在数据层面上的设计其实是数据共享和数据隔离的设计,重点是要在三种设计。

常见的有如下三种设计:

1. 独立数据库实例

2. 共享数据库实例,独立Schema

3. 共享数据库实例、Schema和表,数据切片存储

三种设计方向其实是在平衡数据的共享度、隔离度、复杂度和成本,借用一张图来说明一下。

二、容器化实现多租户设计

1使用镜像隔离租户功能

多租户的应用中的功能经常会出现的一个需求就是按租户开通、或是租户定制化功能,这是最常面临的也是最头疼的问题。

由于产品功能不断的更新迭代,上线发布,随着代码量和功能的越来越多。维护成本也逐渐变大。一种使用容器化的思想来实现的方式如下:

1. 借助各种语音的模块化能力,将功能模块化,代码层级上进行切割。

2. 创建构建脚本,根据租户能力构建功能模块。载入配置、环境变量等信息之后,将编译好的模块构建租户级别特有的镜像

3. 构建完成的镜像按照租户级别、用户量、负载等信息评估需要的资源,完成资源分配、创建容器、运行服务

4. 通过主机用户的管理能力为容器分配负载均衡、域名等访问配置

2租户容器的数据隔离

根据上面提到的集中常见的数据层面的设计可以考虑按照如下的设计完成租户数据存储隔离和通用数据的共享。

1. 通用的数据,由于模型统一,维度一致,读取逻辑可以使用通用的读取模块在编译组合阶段直接放入镜像,同时对其他模块提供统一的代码级别的读取支持。

2. 隔离的数据,可以通过定制化租户特定的仓储实现和单独的数据配置,在编译打包阶段直接隔离掉不同租户的数据。即保障数据安全,也减少了各种租户级别的判断。

三、优缺点

容器化实现多租户的方案由于依托虚拟化,天生自带沙盒特性,虽然由于数据层面上的设计依然存在数据的耦合、隔离等问题,但是随着数据特性的要求不一样只要选择合适的数据方案也可以规避。

优点

· 硬件资源独立分配,CPU、内存都可以按照租户具体负载进行独立分配。

· 对定制化开发友好,功能可以更快速、更独立的开发,并且发布不会影响不相关租户。

· 开发的过程中更关注功能,由于镜像的构建过程物理隔离了功能,开发同学可以更集中在功能的开发上。

· 部署运维成本降低,只需要分配固定的运行时资源即可

· 更利于迁移和独立部署,满足不同部署场景下的租户需求

缺点

· 不太适合微服务的场景,微服务越多,租户镜像向外依赖越大,独立程度越低

· 由于单个容器中存在系统基础设施占用,所以会损耗部分硬件资源