github.com/XiaoMi/Gaea@v1.2.5/docs/multi-tenant.md (about) 1 # 多租户的设计与实现 2 3 ## 背景 4 5 gaea多租户是为了实现一套gaea集群,可以接入多个业务系统的不同数据库,方便部署、运维。gaea多租户为软多租户,一个租户称为一个namespace,多个namespace之间存在于一套gaea proxy集群内,所以是一种软隔离。我们也可以为一些重要等级业务系统单独部署一套gaea集群,甚至一套业务系统对应一套gaea集群实现物理隔离。 6 7 ## 接入方式 8 9 mysql的授权方式为用户名+密码+ip+数据库,接入gaea的情况下,授权方式为用户名+密码确定唯一一个namespace,ip则在白名单IP/IP段起作用,如果未配置白名单IP,则默认对所有IP生效。所以,不同的业务系统,用户名可以有相同的,但是用户名+密码要保证是唯一的,密码我们内部是根据一定的规则随机生成的,并且会校验是否重复。 10 11 ## 实现原理 12 13 ### 主要结构 14 15 在授权阶段还未能确定对应的namespace,所以user和namespace的配置是分别加载的,授权的实现主要依赖于UserManager结构体,其定义如下 16 17 ```golang 18 type UserManager struct { 19 users map[string][]string // key: user name, value: user password, same user may have different password, so array of passwords is needed 20 userNamespaces map[string]string // key: UserName+Password, value: name of namespace 21 } 22 ``` 23 24 ### 配置加载过程 25 26 在系统初始化阶段,会依次加载对应user、namespace配置到一个全局Manager内,其中user部分用以授权检查,整个配置通过滚动数组的方式实现了无锁热加载,具体实现可以参照[gaea配置热加载实现原理](config-reloading.md)一章。 27 28 ### 校验过程 29 30 其中users同一个用户名对应一个string数组,用以处理同一用户名不同密码的情形,而userNamespaces则用以通过用户名+密码快速获取对应的namespace名称。在验证阶段,首先通过CheckUser检查用户名是否存在,不存在则直接授权失败。然后,通过CheckPassword,依次对比确定是否可以找到对应密码,如果找不到,则最终授权失败;如果找到,则授权检查通过并记录对应的会话信息。 31 32 ## 结语 33 34 gaea的多租户确实为部署、运维带来了不少方便,后续也会考虑支持kubernetes的部署、调度多租户等,但是当下的多租户结构不会发生太大变化。