11 Star 38 Fork 21

HuaweiCloudDeveloper / saas-tenant-router-starter

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
Apache-2.0

saas-tenant-router-starter

应用技术mybatis springAop feign hystrix druid hikari

背景

支持多种存储类型组件动态路由,如RDS、*Redis、MQ、ES(规划中)*等; 支持不同存储组件动态加载,即根据后端资源动态开启或者关闭; 支持租户访问零信任安全策略,对访问请求多重校验。

概览图

租户路由概览

原理图

租户路由原理

租户信息传递

Filter过滤器

默认使用TenantDomainInterceptor从request的header中获取租户标识,当使用其他方式传递租户标识时,可以参考TenantContext中HystrixRequestVariableDefault的使用,用于存储租户标识,并在跨服务请求时传递租户标识,在会话结束时需要主动移除。

HystrixRequestVariableDefault

HystrixRequestVariableDefault用于保存一个会话级别的共享变量,需要在父线程中执行HystrixRequestContext.initializeContext(),实现与子线程共享。

配置结构

spring:
  datasource:
    dynamic:
      enable: true # 开关
      effective-pool-name: hikari # 全局指定使用的连接池名称
      default-source: multitenant1 # 默认的数据源组名称
      pools: # 全局连接池配置,可配置等多种连接池
        druid: # 连接池名称,与相关池策略中PoolStrategy.getPoolName()对应
          name: globalDruidConfig
          initial-size: 10
          max-active: 20
          min-idle: 30
        hikari: # 连接池名称,与相关池策略中PoolStrategy.getPoolName()对应
          name: globalHikariConfig
      data-source-map:
        multitenant1: # 数据源组名,其下包含一主多从库配置
          load-balance-strategy: random # 指定负载均衡策略
          effective-pool-name: druid # 组指定使用的连接池名称
          modify-enable: false # 是否允许动态重建数据源,默认关闭
          enable: true # 是否生效,默认为true
          schema-isolation-enable: true # 是否开启schema隔离,默认为false
          pools: # 组内连接池配置,可配置等多种连接池,未配置的属性使用全局配置覆盖
            druid:
              name: dataGroup
              initial-size: 2
              max-active: 3
              min-idle: 1
            hikari:
              max-Pool-size: 100
          master: # 主库,目前支持单主模式
            url: jdbc:mysql://1.1.1.1:3306/housekeeping?useUnicode=true&characterEncoding=utf-8
            effective-pool-name: druid # 库指定使用的连接池名称
            username: xxx
            password: xxx
            driver-class-name: com.mysql.cj.jdbc.Driver
            pools: # 库级别连接池配置,未配置的使用组级别配置覆盖,组级别未配置的使用全局配置覆盖
              druid:
                name: master
          slave: # 从库,目前支持多从模式
            - url: jdbc:mysql://1.1.1.2:3306/housekeeping?useUnicode=true&characterEncoding=utf-8
            		 # 未配置的数据库连接属性,如用户名,密码,driver,未配置时,使用同组内主库配置
              pools: # 库级别连接池配置,未配置的使用组级别配置覆盖,组级别未配置的使用全局配置覆盖
                druid:
                  name: slave
            - url: jdbc:mysql://1.1.1.2:3306/housekeeping?useUnicode=true&characterEncoding=utf-8
              active-pool-name: c3p0 # 库级别,指定连接池类型,选择路径pools下的连接池名,与相关池策略中PoolStrategy.getPoolName()对应 
              pools:
                druid:
                  name: slave
      binding-map: # 租户绑定信息
        0bc92b8e542a4ba9ab35b1de8b1794eb: # 租户标识
          schema: tenant_0bc92b8e542a4ba9ab35b1de8b1794eb # 指定租户绑定schema, 未配置则采用SchemaAdapter所使用策略,未自行扩展时,使用DefaultSchemaAdapter默认选取
          group-name: multitenant1 # 指定数据源组名,选择 data-source-map 配置的组,未指定时,采用DataSourceAdapter所使用策略,未自行扩展时,使用DefaultDataSourceAdapter默认选取

如何使用

1.装配路由插件

目前暂时未发布稳定版本,暂时需要下载源码包使用,发布稳定版本后更新依赖。

2.开启插件

spring:
  datasource:
    dynamic:
      enable: true #开关

3.配置数据源组

spring:
  datasource:
    dynamic:
      enable: true #开关
      data-source-map:
        multitenant1: #数据源组名,其下包含一主多从库配置
          modify-enable: false # 是否允许动态重建数据源,默认关闭
          enable: true # 是否生效,默认为true
          schema-isolation-enable: true # 是否开启schema隔离,默认为false
          master: # 主库,目前支持单主模式
            url: jdbc:mysql://1.1.1.1:3306/housekeeping?useUnicode=true&characterEncoding=utf-8
            username: xxx
            password: xxx
            driver-class-name: com.mysql.cj.jdbc.Driver
          slave: # 从库,目前支持多从模式
            - url: jdbc:mysql://1.1.1.2:3306/housekeeping?useUnicode=true&characterEncoding=utf-8
            		 # 未配置的数据库连接属性,如用户名,密码,driver,未配置时,使用同组内主库配置
            - url: jdbc:mysql://1.1.1.3:3306/housekeeping?useUnicode=true&characterEncoding=utf-8

需要在data-source-map路径之下配置数据源组,key=数据源组名称, 此名称不可重复。数据源组内可配置一主多从,主库路径为master,从库路径为slave,可配多个从库。主库或者从库可配置数据库连接信息如连接地址url,用户名username,密码password,驱动driver-class-name。当从库未配置username,password,driver-class-name时,会默认使用同组中主库的对应配置。url必须配置,为防止误配,此项未作为缺省配置。

spring.datasource.dynamic.data-source-map.*.enable 数据源是否生效开关

spring.datasource.dynamic.data-source-map.*.modify-enable 是否允许动态重建数据源开关,默认false关闭,当开启时,可以通过修改属性并出发refresh事件(参考spring-cloud-config)达到使用最新配置重建当前数据源组的目的

spring.datasource.dynamic.data-source-map.*.schema-isolation-enable 数据源组是否开始schema隔离,默认为false关闭,当开启时,必须为绑定此数据源组的租户绑定一个有效的schema,否则路由失败;关闭时,忽略绑定的schema,默认路由到默认schema

4.配置连接池

spring:
  datasource:
    dynamic:
      pools: # 全局连接池配置,可配置等多种连接池
        druid: # 连接池名称,与相关池策略中PoolStrategy.getPoolName()对应
          name: globalDruidConfig
          initial-size: 10
          max-active: 20
          min-idle: 30
        hikari: # 连接池名称,与相关池策略中PoolStrategy.getPoolName()对应
          name: globalHikariConfig
      data-source-map:
        multitenant1: #数据源组名,其下包含一主多从库配置
          pools: # 组内连接池配置,可配置等多种连接池,未配置的属性使用全局配置覆盖
            druid:
              name: dataGroup
              initial-size: 2
              max-active: 3
              min-idle: 1
          master: # 主库,目前支持单主模式
            pools: # 库级别连接池配置,未配置的使用组级别配置覆盖,组级别未配置的使用全局配置覆盖
              druid:
                name: master
          slave: # 从库,目前支持多从模式
            - url: jdbc:mysql://1.1.1.2:3306/housekeeping?useUnicode=true&characterEncoding=utf-8
            		 # 未配置的数据库连接属性,如用户名,密码,driver,未配置时,使用同组内主库配置
              pools: # 库级别连接池配置,未配置的使用组级别配置覆盖,组级别未配置的使用全局配置覆盖
                druid:
                  name: slave

在配置的多个层级中都支持配置连接池属性,配置路径如下:

路径spring.datasource.dynamic.pools下的连接池配置为全局配置,会被更细粒度的配置覆盖。

路径spring.datasource.dynamic.data-source-map.*.pools下的配置为数据源组级别的配置,路径中的 * 代表数据源组名称, 需要使用全小写, 名称中 - 将不会转换为首字母大写。

路径spring.datasource.dynamic.data-source-map.*.master.pools下的配置为主库级别的配置

路径spring.datasource.dynamic.data-source-map.*.slave.pools下的配置为从库级别的配置

当主库或者从库有属性未配置时,此属性将会使用其所属数据源组的同名称的连接池的配置,所属数据源组仍未配置时,此属性继续向上使用全局连接池配置,仍未找到,则为空。

pools之下配置的key为连接池名称,或可以称为类型,从下至上配置的属性进行覆盖时,按照连接池名称查找。连接池名称对应代码中PoolStrategy.getPoolName()获取的值。目前已实现druid,hikari连接池,每一个连接池类型需要新增两个java类,用于承载池属性配置和创建连接池,均属于PoolStrategy的子类。

连接池属性类,用于承载连接池属性的类需要实现 JdbcPool接口,此接口继承PoolStrategy。

连接池创建类,用于实现数据源创建功能的类需要实现DataSourceCreator接口,此接口继承PoolStrategy。目前已有druid,hikari的实现,可参考。

如果有需要扩展自定义连接池,需要做到三点:1.新增连接池属性类,需实现JdbcPool接口。2.新增数据源创建类实现DataSourceCreator接口。3.以上两个实现的getPoolName() 返回的值将会当做池名称,读取*.*..pools之下的相匹配的key所对应的配置信息。

主库和从库之间的连接池配置相互独立。

5.指定连接池

spring:
  datasource:
    dynamic:
      enable: true #开关
      effective-pool-name: druid # 全局指定使用的连接池名称
      data-source-map:
        multitenant1: #数据源组名,其下包含一主多从库配置
          effective-pool-name: druid # 组指定使用的连接池名称
          master: # 主库,目前支持单主模式
            url: jdbc:mysql://1.1.1.1:3306/housekeeping?useUnicode=true&characterEncoding=utf-8
            active-pool-name: druid # 库指定使用的连接池名称
          slave: # 从库,目前支持多从模式
            - url: jdbc:mysql://1.1.1.2:3306/housekeeping?useUnicode=true&characterEncoding=utf-8
              active-pool-name: c3p0 # 库级别,指定连接池类型,选择路径pools下的连接池名,与相关池策略中PoolStrategy.getPoolName()对应 

指定连接池的属性与连接池配置类似,

spring.datasource.dynamic.active-pool-name 为全局配置

spring.datasource.dynamic.data-source-map.*.effective-pool-name 为数据源组级别配置

spring.datasource.dynamic.data-source-map.*.master.effective-pool-name 为主库配置

spring.datasource.dynamic.data-source-map.*.slave.effective-pool-name 为从库配置

当主库或者从库未配置时,使用所属数据源组的组级别配置,组未配置时,使用全局配置,如果全局配置仍未配置,则默认使用hikari连接池。

6.指定负载均衡策略

spring:
  datasource:
    dynamic:
      data-source-map:
        multitenant1: #数据源组名,其下包含一主多从库配置
          load-balance-strategy: random # 指定负载均衡策略

负载均衡策略配置路径spring.datasource.dynamic.data-source-map.*.load-balance-strategy,各组单独配置,如未配置,则默认使用随机算法进行负载均衡。

目前只实现了随机算法,如有需要扩展,可以实现LoadBalanceStrategy接口扩展,算法类型为LoadBalanceStrategy.getStrategyType(),如果使用扩展算法,必须在配置中显示指定算法类型,否则使用随机算法。

7.租户绑定数据源

spring:
  datasource:
    dynamic:
      default-source: multiTenant1 # 默认的数据源组名称
      binding-map: # 租户绑定信息
        0bc92b8e542a4ba9ab35b1de8b1794eb: # 租户标识
          group-name: multitenant1 # 指定数据源组名,选择 data-source-map 配置的组,未指定时,采用DataSourceAdapter所使用策略,未自行扩展时,使用DefaultDataSourceAdapter默认选取

绑定路径为spring.datasource.dynamic.binding-map.*.group-name 指定数据源组名称, * 为租户标识。DataSourceBindingStrategy的扩展实现来获取绑定的数据源,如果未添加自定义扩展,将会采用默认的数据源策略DefaultDataSourceBindingStrategy获取数据源,获取逻辑为优先使用spring.datasource.dynamic.default-source 指定的数据源组,如果default-source未配置,则判断已配置的数据源组列表中是否只有一组数据源,是则选择这一个组作为数据源使用,否则获取的数据源为空,选择数据源失败。

8.租户绑定schema

spring:
  datasource:
    dynamic:
      enable: true #开关
      binding-map: # 租户绑定信息
        0bc92b8e542a4ba9ab35b1de8b1794eb: # 租户标识
          schema: tenant_0bc92b8e542a4ba9ab35b1de8b1794eb # 指定租户绑定schema, 未配置则采用SchemaAdapter所使用策略,未自行扩展时,使用DefaultSchemaAdapter默认选取

此配置仅针对使用schema隔离的场景使用,绑定路径为spring.datasource.dynamic.binding-map.*.schema 指定的schema, *为租户标识,当某个租户标识未在此绑定schema时,将会使用SchemaBindingStrategy的扩展实现来获取租户对应的schema,如果未自定义扩展,则使用DefaultSchemaBindingStrategy来获取schema。

自定义扩展中,可以使用按既定规则拼接,数据库表存储,缓存或者其他任意方式根据租户标识获取。

9.数据源动态变更

在不重启服务前提下,通过配置中心修改spring.datasource.dynamic之下的数据库连接属性或者连接池属性配置,可以根据最新的配置重建,新增,关闭数据源。此功能默认是处于关闭状态,当某个数据源组需要开启支持动态变更时,需要配置属性spring.datasource.dynamic.data-source-map.*.modify-enable=true,当修改连接池属性后,需要重建连接池时,需要实现PoolRefreshProcessor接口,用于确定修改哪些参数需要触发重建,修改之后需要触发RefreshScopeRefreshedEvent事件,用于触发变更(使用spring-cloud-config作为配置中心时,调用/actuator/busrefresh即可,其他未使用spring事件机制的配置中心,需要添加事件触发机制)。连接池属性与数据库连接属性之外的其他配置,修改立即生效。

变更支持的场景如下:

1.新增数据源组

2.关闭数据源组,需配置spring.datasource.dynamic.data-source-map.*.enable=false

3.组被新增slave

4.组被修改数据库连接属性或者连接池属性

5.组内关闭slave,需配置spring.datasource.dynamic.data-source-map.*.salve.0.enable=false

6.组内删除配置也可以关闭对应库的连接池

当使用此项功能时,请关注对应的日志,确定数据源的变更结果。

10.事务

目前仅支持基于注解@Transactional的声明式事务,当使用事务时,数据源切换为master主库。

Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: You must give any other recipients of the Work or Derivative Works a copy of this License; and You must cause any modified files to carry prominent notices stating that You changed the files; and You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS

简介

SaaS:支持多种存储类型组件动态路由,如RDS、Redis、MQ、ES等; 支持不同存储组件动态加载,即根据后端资源动态开启或者关闭; 支持租户访问零信任安全策略,对访问请求多重校验。 展开 收起
Java 等 2 种语言
Apache-2.0
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
Java
1
https://gitee.com/HuaweiCloudDeveloper/saas-tenant-router-starter.git
git@gitee.com:HuaweiCloudDeveloper/saas-tenant-router-starter.git
HuaweiCloudDeveloper
saas-tenant-router-starter
saas-tenant-router-starter
master-dev

搜索帮助