上篇记录说道了,对象属性的保存,简单的提及了一下保存过程,今天我记录一下,thingsboard中对于实体保存的并发操作。
由于物联网系统中连接的设备众多,大家也知道,信息的保存往往是并发中一个瓶颈存在,thingsboad在这方面做了并发的异步处理,我根据我的理解整理一下,以备查阅或者叫做梳理学习以备在需要用的地方取用。
由于在我改造的系统中,舍弃了thingsboard的持久化层,直接用mybaits-plus替换,中间去掉了thingsboard好多中间对象。这个有多方面原因,大神们就先不要喷我,等以后改造过程中我们再详细就这个问题展开讨论。所以这个系统中直接的对象持久化逻辑非常简单,直接使用jeecg-boot的框架进行处理。
所以就在things实现的并行处理框架直接嫁接了mybaits-plus的处理。我们来分析一下属性保存的具体实现,thingsboard中属性保存具体实现类为JpaAttributeDao这个组件会读取配置文件中的一些参数,如处理线程数,以及延时等参数,用于构建并发处理。组件初始化函数init中构建了并行处理队列我大概记录一下
@PostConstruct private void init() { TbSqlBlockingQueueParams params = TbSqlBlockingQueueParams.builder() .logName("Attributes") .batchSize(batchSize) .maxDelay(maxDelay) .statsPrintIntervalMs(statsPrintIntervalMs) .statsNamePrefix("attributes") .batchSortEnabled(batchSortEnabled) .build(); //根据配置文件生成配置参数 Function<AttributeKv, Integer> hashcodeFunction = entity -> entity.hashCode(); //hashcode函数构造 queue = new TbSqlBlockingQueueWrapper<>(params, hashcodeFunction, batchThreads, statsFactory);//构建数据保存队列 queue.init(logExecutor, v -> attributeKvRepository.saveOrUpdateBatchByMultiId(v), Comparator.comparing((AttributeKv attributeKvEntity) -> attributeKvEntity.getEntityId()) .thenComparing(attributeKvEntity -> attributeKvEntity.getAttributeKey()) );//初始化数据保存附列,传入log执行器,以及保存实体的函数。最后一个参数好像排序用,还没有弄明白,知道的大神可以指导一二。 }
TbSqlBlockingQueueWrapper这个类是thingsboard专门为处理并发实现的一个类,主要分析一下他的初始化函数
public void init(ScheduledLogExecutorComponent logExecutor, Consumer<List<E>> saveFunction, Comparator<E> batchUpdateComparator) { for (int i = 0; i < maxThreads; i++) { MessagesStats stats = statsFactory.createMessagesStats(params.getStatsNamePrefix() + ".queue." + i); TbSqlBlockingQueue<E> queue = new TbSqlBlockingQueue<>(params, stats); queues.add(queue); queue.init(logExecutor, saveFunction, batchUpdateComparator, i); } }
可以看出来,根据线程数量,创建了相应的
TbSqlBlockingQueue执行队列,具体执行逻辑也是有这个类来实现。并且在执行完毕以后,做相应的成功失败的统计,以及log的打印保存等。
我大概看了一下,基本所有的对象保存过程,都重用上面提到的组件。既然thingsboard这样处理,我想肯定在并发上有比较的表现。在这里记录一下过程,免得以后又在代码里绕来绕去找不到实现的地方。