1、什么是多租户? 项目中是怎么实现多租户的? 用到了哪些技术实现?

SaaS系统下,实现多个商户“服务共享,数据隔离”;
02-多租户实现流程.png

多租户实现方案:
1、应用层数据层都隔离:每个租户使用独立的应用程序、数据库。
2、应用层共享数据库层隔离:应用程序仅部署一套,所有租户实例共享,租户仍拥有自己独立的数据库,应用程序需对接多个租户的数据库。
3、应用层数据库层共享数据隔离(saas系统的主流,也是项目中采用)
应用程序和数据库仅部署一套,所有租户共享,==多个或所有租户共享DataBase,也就是说共同使用一个数据库,而数据则使用表字段进行数据隔离==。如表中增加TenantID多租户的数据字段。这是共享程度最高、隔离级别最低的模式,简单来讲,即每插入一条数据时都需要有一个客户的标识。这样才能在同一张表中区分出不同客户的数据,这也是我们系统目前用到的==【enterprise_id和store_id】==。
image.png
实现技术:
Mybatis-plus的多租户插件:基于Mybatis Interceptor插件【拦截器TenantLineInnerInterceptor)】

2、各个系统平台如何分析数据库表是否需要忽略?

根据业务需求,看是否需要进行数据隔离,如在运营平台,则运营商管理的是所有商户所有门店,所以不需要拼接sql,故运营平台的数据库中的表基本都需要添加在忽略表中,如tab_places、tab_affix等;

3、我们平台租户字段有几个,分别是如何传递到各个服务工程的?

商户号值传递过程.png
项目中是使用mybatis-plus的多租户插件TenantLineInnerInterceptor获取商户id实现多租户在应用层数据库层服务共享、数据隔离方案,商户id的整个传递过程如下:
1、认证服务:用户登录平台时会进行认证,通过认证后,会给用户颁发一个jwtToken,并在jwtToken存储用户信息、商户id、门店id;
2、前端服务:前端收到认证成功响应的结果后,将jwtToken存储到localStorage中;
3、发起请求:此时,用户在系统中每一次发起请求,都被拦截,在请求头中添加jwtToken;
4、网关服务:收到前端nginx的反向代理请求后,使用全局过滤器filter拦截请求,并获取请求头中jwtToken,解析为current_user=userVoString存放在请求头中;
5、发起Http协议调用web相关服务;
6、使用SpringMVC拦截器拦截请求,获取请求头中current_user=userVoString【用户信息】;
7、RPC隐式传参:TenantIntercept从请求头中拿到用户信息后,存放到当前线程中,放入当前RpcContext中;
(RpcContext内部有一个ThreadLocal变量,它是作为ThreadLocalMap的key,表明每个线程有一个RpcContext)
8、拼接Sql:mybatis-plus的多租户插件TenantLineInnerInterceptor会拦截要执行的sql,并根据sql中的表名判断该表是否在忽略表中,不在则拼接商户的id进行隔离。

场景面试题:
1.你们现在的SASAS权限控制是怎么设计的?
基于角色权限五张表,认证流程
2.你们权限控制的时候区分商家吗?当前每个商家的权限是不是一样的?
只控制到商家级别(没有完成不同商家不同角色)
3.如果让你去设计一个不同商家的不同权限怎么设计?
在存储角色也区分商户号,结合权限控制,把角色管理的这个权限下放到商家系统控制