平台化多租户架构实践

本文由用户“cba265”分享发布 更新时间:2021-02-16 13:22:53 举报文档

以下为《平台化多租户架构实践》的无排版文字预览,完整格式请下载

下载前请仔细阅读文字预览以及下方图片预览。图片预览是什么样的,下载的文档就是什么样的。

KK平台化多租户架构实践

——初探

一、模块工程搭建 2

二、单表自动生成dao层增删改查方法 7

三、jenkins添加模块和小程序 8

四、meShow api多租户实践 11

五、kkrpc模块多租户实践 11

六、melot-jedis Redis数据缓存多租户实践 12

七、melot-cache-util本地内存缓存多租户实践 13

八、MQ 消息生产消费多租户实践 14

九、小程序多租户任务实践 16

十、Mybatis sharding-jdbc 多租户数据源实践 16

十一、disconf多租户差异化配置实践 17

十二、日志框架melot-log实践 17

原理及背景介绍 17

melot-log扩展支持的新feature 17

melot-log接入方式 18

melot-log配置文件示例 18

melot-log程序中应用 20

创建新的Logger 20

业务日志打印 20

业务指标数据埋点方法 20

业务指标数据埋点应用实例 21

附录 22

Spring boot配置文件示例: 22

一、模块工程搭建

基于新开发的骨架模板(kk-module-quickstart-archetype) 快速搭建模块api、服务和小程序

骨架maven配置:

com.melot.module

kk-module-quickstart-archetype

2.7.0

地址: http://maven.kktv2.com:8081/nexus/content/repositories/releases

模块api生成后需要手动将parent标签删除,否则jar包上传会有问题

IDEA配置

/

基于骨架模板新建工程:

选中最新版的骨架模板

/

输入组名和模块业务名称:

组名统一命名:com.melot.kk

模块业务名称:以模块本身的业务含义来命名,例如欢乐PK模块就叫nationalPK

/

添加包某某:由GroupId+ArtifactId组成(eclipse里面会自动添加)

/

输入工程名称:kk-ArtifactId-module组成(eclipse里面会自动添加)

/

创建完成后的工程目录结构如下:

api结构如下:

/

小程序结构如下:

/

server结构如下:

/

eclipse配置:

/

/

二、单表自动生成dao层增删改查方法

编辑resources目录下的这2个文件:

/

运行mybatis-generator命令生成dao层对应的增删改查方法

/

server层查询列表方法示例:

@Override public Result getHistDeliveryDOList(Integer deliveryUserId, String detailAddress) { HistDeliveryExample conditions = makeQueryConditions(deliveryUserId, detailAddress); List histDeliveries = histDeliveryMapper.selectByExample(conditions);; List histDeliveryDOs = Lists.newArrayList(); if(histDeliveries != null) { for(HistDelivery histDelivery : histDeliveries) { HistDeliveryDO histDeliveryDO = getHistDeliveryDO(histDelivery); histDeliveryDOs.add(histDeliveryDO); } } return new Result(CommonStateCode.SUCCESS,"调用成功", histDeliveryDOs); }

private HistDeliveryExample makeQueryConditions(Integer deliveryUserId, String detailAddress) { HistDeliveryExample example = new HistDeliveryExample(); HistDeliveryExample.Criteria criteria = example.createCriteria(); if(deliveryUserId != null) { criteria.andDeliveryUserIdEqualTo(deliveryUserId); } if(StringUtils.isNotEmpty(detailAddress)) { criteria.andDetailAddressLike("%" + detailAddress + "%"); } example.setOrderByClause("create_time desc"); return example; }

三、jenkins添加模块和小程序

添加模块:

/

/

添加小程序:

/

/

/

四、meShow api多租户实践

API作为后台对外提供服务的重要窗口,需要根据来自不同租户方用户请求中的租户ID(TenantId)来进一步向后端底层服务发起请求。采用隐式传参的方式来获取租户ID。具体操作流程为:API网关层根据请求的服务器域名来设置对应的租户ID到http request的header中,API服务处理业务http请求前增加一个拦截器读取request header中租户ID参数,不存在时默认租户ID为0,设置租户ID到当前线程租户上下文变量中,后续业务操作中需要区分租户ID时则直接从当前线程租户上下文中获取租户ID即可。

租户上下文信息的设置和获取依赖melot-utils包

com.melot.common

melot-utils

接口操作方法为:

TenantContext.getContext().getTenantId() //获取当前线程上下文中的租户ID

TenantContext.getContext().setTenantId(tenantId) //设置租户ID到当前线程租户上下文

五、kkrpc模块多租户实践

为了减少代码维护成本,kkrpc模块跨进程调用过程中,同样采用隐式传递租户上下文的方式。新版kkrpc模块框架中支持了rpc调用过程中租户上下文的隐式传递。实现原理为:客户端发起RPC调用时自动获取当前线程的租户上下文信息添加到rpc请求包的扩展字段中,同rpc请求一起发送到服务端,服务端收到rpc请求后,如果发现请求扩展字段中存在租户上下文信息则解析读取并设置到服务端当前业务处理线程中。同样后续模块业务操作中需要区分租户ID时则直接从当前线程租户上下文中获取租户ID即可

服务的生产者配置基于注解(@RpcService)生成:

@Service @RpcService(interfaceName = "com.melot.kk.test.api.service.DemoService", version = "1.0.0") public class DemoServiceImpl implements DemoService {

服务的调用方也基于注解(@RpcConsumer)来调用:

@Component public class SpringSimpleJob implements SimpleJob {

private static Logger logger = Logger.getLogger(SpringSimpleJob.class); @RpcConsumer private DemoService demoService; @RpcConsumer(version = "1.0.8") private ActorService actorService; int i = 0; @Override public void execute() { RoomInfo roomInfo = actorService.getRoomInfoById(***); i++; logger.info(i + "tenantId:" + TenantContext.getContext().getTenantId() + " roomInfo: " + new Gson().toJson(roomInfo)); } }

六、melot-jedis Redis数据缓存多租户实践

引入依赖:

com.melot

melot-jedis-spring-boot-starter

在application.propeties中配置jedis相关属性,指定tenantId为对应租户的对应sourceName对应的配置。如下例配置了两个sourcename为relation的single source, 租户id为默认值0的对应redis1.kktv2.com等的配置,租户id为10086的对应redis2.kktv2.com

/

使用方式和starter的旧版本相同,会根据是否使用了多租户而注册原始的JedisWrapper。

@Autowired

Qualifier("relation")

private JedisWrapper userCache;

七、melot-cache-util本地内存缓存多租户实践

由melot-cache-util支持多租户的本地缓存。实现原理为:melot-cache-util根据不同的租户id生成不同的实例化对象,内部根据缓存操作时当前线程的租户上下文切换到对应的Cache实例上进行操作。

开发中需要引用的melot-cache-util工具包:

com.melot.module melot-cache-util 2.0.1

使用方法如下示例:

JsonObject jsonObject = EhCache.getFromCache(key, JsonObject.class);

EhCache.putInCacheByLive(key, result, cacheTime);

八、MQ 消息生产消费多租户实践

后续新的功能中状态变更都需要发出相应的 MQ 消息

生产者配置:

# mq配置 生产者 租户0 melot.mq.history[0].mqInstance=kk-test-history melot.mq.history[0].mqNsAddr=mq1.kktv2.com:9876;mq2.kktv2.com:9876 melot.mq.history[0].producerName=kk-test-producer melot.mq.history[0].clientIp= melot.mq.history[0].sendTimeout=2000 melot.mq.history[0].tenantId=0 # mq配置 生产者 租户1 melot.mq.history[1].mqInstance=kk-test-history melot.mq.history[1].mqNsAddr=10.0.13.23:9876 melot.mq.history[1].producerName=kk-test-producer melot.mq.history[1].clientIp= melot.mq.history[1].sendTimeout=2000 melot.mq.history[1].tenantId=1

生产者代码:

@Component public class SpringOneTimeJob implements OneTimeJob {

@Autowired private KKHistory kkhistory; @Override public void process() { int tenantId = TenantContext.getContext().getTenantId(); // 发送MQ消息 ActionHistory catchDollAction = kkhistory.newActionHistory("catchDollSuccessTopic"); catchDollAction.setMsgKey(String.valueOf(tenantId)); catchDollAction.addActionData("catchDollRecordId", 10086); catchDollAction.addActionData("userId", ***); catchDollAction.addActionData("nickname", "你好"); catchDollAction.complete(); } }

消费端配置:

/

@Component public class SpringOneTimeConsumerJob { private static Logger logger = Logger.getLogger(SpringOneTimeConsumerJob.class); @RpcConsumer DemoService demoService; @Bean public HistoryProcessor getHistoryProcessor() { return new ActionHistoryProcessor() { @Override public boolean process(MessageExt messageExt, ActionHistory actionHistory) { int tenantId = TenantContext.getContext().getTenantId(); CatchDollRecordDO catchDollRecordDO = demoService.getCatchDollRecordDO(129277).getData(); String nickname = catchDollRecordDO.getNickName(); int userId = catchDollRecordDO.getThirdRecordId(); logger.info("tenantId:" + tenantId + " 昵称:" + nickname + " userId:" + userId + " -->start SpringOneTimeConsumerJob job..."); logger.info("consumer actionHistory: " + new Gson().toJson(actionHistory)); return true; } }; } }

九、小程序多租户任务实践

多租户需要提供一套相同业务代码的不同租户id执行的小程序。为了方便开发和改造,在之前的melot-ejob-spring-boot-starter基础上提供了基于配置,即可实现多个相同任务,不同租户的调度和监控。

在原有的ejob配置基础上添加tenantIds属性,设置租户id以逗号分隔符分割,即可启动对应租户数量的线程,每个线程含有对应的租户id变量。具体小程序框架starter的配置如下:

# elasticJob配置 melot.elasticJob.regCenter.serverList=zk1.kktv2.com:2181,zk2.kktv2.com:2181,zk3.kktv2.com:2181 melot.elasticJob.regCenter.namespace=api-melot-job melot.elasticJob.simpleJob[0].cron=0/10 * * * * ? melot.elasticJob.simpleJob[0].jobName=springSimpleJob melot.elasticJob.simpleJob[0].refJobName=springSimpleJob melot.elasticJob.simpleJob[0].email=jian.sheng@melot.cn melot.elasticJob.simpleJob[0].host=10.0.*.* melot.elasticJob.simpleJob[0].tenantIds=0 melot.elasticJob.oneTimeJob[0].jobName=springOneTimeJob melot.elasticJob.oneTimeJob[0].refJobName=springOneTimeJob melot.elasticJob.oneTimeJob[0].email=jian.sheng@melot.cn melot.elasticJob.oneTimeJob[0].ho 内容过长,仅展示头部和尾部部分文字预览,全文请查看图片预览。 is.single[1].sourceName=userdata

melot.redis.single[1].tenantId=1

melot.redis.single[1].connectionHost=10.0.1.219

melot.redis.single[1].connectionPort=6380

melot.redis.single[1].connectionTimeOut=5000

melot.redis.single[1].connectionDatabase=1

melot.redis.single[1].maxActive=10

melot.redis.single[1].maxIdle=5

melot.redis.single[1].minIdle=1

melot.redis.single[1].testOnBorrow=true

melot.redis.single[1].testOnReturn=true

melot.redis.single[1].testWhileIdle=true

melot.redis.single[1].maxWait=3000

[文章尾部最后500字内容到此结束,中间部分内容请查看底下的图片预览]请点击下方选择您需要的文档下载。

  1. 会计技能实践报告1
  2. 教学设计 李丹
  3. 文明租房公约
  4. 2019-2020学年第2学期《概论》课程实践报告
  5. 消防报警系统疑难故障判断处理方法!
  6. 附件5:大学暑期社会实践记录表(个人)
  7. 大学机电一体化实训办公自动化实践报告
  8. 专业学位研究生实习实践报告表
  9. 公共卫生硕士专业实践报告信息采集专业实践报告
  10. 四年级综合实践教学计划
  11. Ahealthylife
  12. 2018年国培返岗实践总结
  13. 教师的实践反思
  14. 教学设计(实践反思)
  15. 关于开展2020年大学寒假社会实践的通知
  16. 寒假实践心得
  17. **_*实践考核表林某某
  18. 《小王子》英文读后感
  19. 走遍美国 听力练习1.1
  20. 学前教育专业课程设置方案

以上为《平台化多租户架构实践》的无排版文字预览,完整格式请下载

下载前请仔细阅读上面文字预览以及下方图片预览。图片预览是什么样的,下载的文档就是什么样的。

图片预览