SpringBoot+Mybatis Plus 多租户动态数据源
背景
需求场景是需要实现一个支持多租户多数据源的系统,每个租户的数据库完全隔离。并且系统需求通过区分不同租户的请求进行动态数据源的切换。
系统底层框架是使用的SpringCloud + MyBatisPlus(一个mybatis的增强框架),数据库连接池是Druid。
熟悉SpringBoot的同学都知道SpringBoot本身是可以配置多个数据源的,但是SpringBoot的多数据做不到动态的切换,只能在代码里面通过注解或写死。
基于以上情况,设计实现了一个动态切换数据源的实现方案。
实现功能
通过域名进行租户自动识别
通过租户识别信息,动态的选择数据源
各个spring微服务之间进行租户信息传递
通过注射方式进行强制数据源制定
下面介绍一下功能的核心实现。
核心实现
租户识别
租户信息的识别通过Nginx代理来实现,核心思路就是域名中包含租户信息,然后通过Nginx代理时,在请求头和相应头中添加租户的识别信息。
如上配置后,通过Nginx代理后的请求都会带上租户信息。eg: abc.zane.com通过这个域名访问系统时会识别出租户为abc。
动态切换
这个是方案的核心部分,重写了MyBatis的数据源初始化过程。
讲解一下核心实现原理及核心的代码部分。
主要通过以下步骤实现:
配置Spring拦截器,设置租户标示。
自定义拦截器,拦截先前Nginx设置的租户信息,并设置到DataSourceTenantContextHolder中。
将租户信息设置到InheritableThreadLocal中,实现线程内的租户信息可见。
将自定义拦截器加到Spring容器中。
通过以上实现了一个请求内的租户信息可见。
重写MyBatis的数据源初始化
使用自定义数据源实现DynamicDataSource代替原始的DruidDataSource。
将自定义的数据源设置到MyBatis的工产类中
通过租户标示初始化数据
数据源需要实现通过租户来初始化的逻辑,具体的初始化可以按需求实现initDatasource方法。
租户传递
基于SpringCloud各个服务间是通过Feign来通信,那么只要实现一个简单的Feign拦截器就可以。
注释指定数据源
自定义一个租户的注解类
通过环绕型的AOP拦截, 在打了注解的方法上进行租户的切换。实现注解指定数据源。
思考
上面方法基本已经满足了前面的需求,可以做到不同租户的动态数据源的切换。
但是还是有许多地方需要完善,比如:
不同租户的数据源的缓存,避免重复初始化
重写了MyBatis的工厂类,那么MyBatis plus的相关特性怎么保留。
如果一个租户下也有多个数据怎么实现
大家可以思考一下这些问题。
版权声明: 本文为 InfoQ 作者【zane】的原创文章。
原文链接:【http://xie.infoq.cn/article/7f8655c237bca715870d4f648】。文章转载请联系作者。
评论