多租户适配、多租户隔离

多租户适配

很多产品只有专属化版本,需要从产品底层进行尽量少的改造,满足上云之后多租户的数据、缓存、定时任务等隔离

多租户适配条目

条目名称 适配方案
持久层适配 支持schema和字段隔离两种方案
quartz定时任务 上下文无法获取租户信息,通过JobGroup识别
reids缓存 缓存key体现租户id即可
websocket场景 从cookie获取、前端调用diwork的api获取租户信息塞到cookie,后端websocket握手后从cookie获取
1. 持久层适配

考虑到本身业务的实际情况,要求数据源同时支持schema隔离和字段隔离,持久层的多租户适配业务代码需要零感知、无侵入,适配实现过程如下:

STEP-1. 表结构改造,追加租户字段、有预置脚本的表,需要跟租户字段建立联合主键;
STEP-2. 引入动态数据源,动态数据源查询租户信息,切换schema实现租户按schema隔离;
STEP-3. 改造dao,采用cglib加入Interceptor,在dao层方法的执> 行前加入拦截;
STEP-4. 用jsqlParser编写sql解析类,第3步拦截到的sql追加租户ID的条件;

动态数据源关键代码

获取租户信息中的schema信息,根据schema信息切换,租户信息通过rest接口获取,考虑了到性能已加ThreadLocal和redis两重缓存

protected Connection changeCatalog(Connection con) throws SQLException {
        String tenantId = InvocationInfoProxy.getTenantid();
        if (StringUtils.isBlank(tenantId)) {
            tenantId = "tenant";
        }
        String catalog = this.getCatalog(tenantId);
        if (StringUtils.isNotBlank(catalog)) {
            try {
                con.setCatalog(catalog);
            } catch (SQLException e) {
                logger.error("Error occurred when setting catalog for connection, Tenant ID is {}", tenantId);
                con.close();
                throw e;
            }
        } else {
//            logger.error("Switching catalog failed, check tenant ID -> {}!", tenantId);
            String defaultCatalog = PropertyUtil.getPropertyByKey("jdbc.catalog");
            if (StringUtils.isNotBlank(defaultCatalog) && !defaultCatalog.equals(con.getCatalog())) {
                con.setCatalog(defaultCatalog);
                logger.info("reset catalog for connection success!");
            }
        }
        return con;
    }
dao层改造关键代码
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值