ThingsBoard 二次开发之源码分析 4-启动分析 3
ThingsKit物联网平台
ThingsKit物联网平台可提供跨不同设备和数据源的通用PaaS服务,在整个物联网架构中起到承上启下的中介作用,联动感知层及应用层之间的所有交互——向下连接、管理物联网设备端并完成感知数据的归集与存储,向上为应用开发商与系统集成商提供应用开发的统一数据接口及共性模块工具。在实现“物联”的基础之上,感知层与应用层频繁交互过程中,产生的数据具有体量大、种类多、动态滚动的特征,物联网平台作为产业链中的核心枢纽,更是应用融合以及数据价值孵化的土壤,除提供基础设施服务支撑设备间的数据交换外,通过对平台数据的处理、分析和可视化,将数据赋能过程大幅前置,充分发挥规模效应,实现数据即生产即处理,便于数据快速应用落地,简化物联网解决方案的复杂度并降低方案成本,充当“加速层”,推进各层在应用场景的落地速度与进程。
ThingsKit物联网平台:基于ThingsBoard开发,面向中小型企业开箱即用的低代码物联网平台 :ThingsKit物联网平台
ThingsKit物联网平台演示环境 :https://docs.thingskit.com/thingskit-link/getting-started
欢迎加入ThingsBoard技术交流群
这里可复制Q群号:69998183
关注“云腾五洲”:获取二开ThingsBoard物联网平台演示
TK物联网平台:ThingsKit物联网平台
#ThingsBoard源码分析4-启动分析3
***以下的分析环境基于默认配置***
## 1. Actor 模型
首先搬用[官网](https://thingsboard.io/docs/reference/architecture/)关于Actor模型的介绍:
![actor架构图](https://cdn.iotschool.com/photo/2020/b141c2c4-7557-4b5e-bb6d-91bbe0c62508.png?x-oss-process=image/resize,w_1920)
- The brief description of each actor’s functionality is listed below:
- **App Actor** - responsible for management of tenant actors(负责管理租户Actor). An instance of this actor is always present in memory.
- **Tenant Actor** - responsible for management of tenant device & rule chain actors(负责管理租户设备,规则链Actor). An instance of this actor is always present in memory.
- **Device Actor** - maintain state of the device: active sessions, subscriptions, pending RPC commands(处理设备状态,激活session,订阅,RPC请求), etc. Caches current device attributes in memory for performance reasons. An actor is created when the first message from the device is processed. The actor is stopped when there is no messages from devices for a certain time.
- **Rule Chain Actor** - process incoming messages and dispatches them to rule node actors(处理消息,并将消息分发给node Actor). An instance of this actor is always present in memory.
- **Rule Node Actor** - process incoming messages, and report results back to rule chain actor(处理消息,并将处理的消息返回给规则链Actor). An instance of this actor is always present in memory.
## 2. Actor启动分析
![DefaultActorService简析](https://cdn.iotschool.com/photo/2020/633f6162-71be-409e-925e-762d51e29b19.png?x-oss-process=image/resize,w_1920)
图片看不清楚的,请点击这里:
- 标准:https://cdn.iotschool.com/photo/2020/633f6162-71be-409e-925e-762d51e29b19.png?x-oss-process=image/resize,w_1920
- 高清:https://pic.downk.cc/item/5f50c6b1160a154a67353d2e.png
`DefaultActorService`中`@PostConstruct`标记的`initActorSystem()`开启了actor的启动流程:
```java
public void initActorSystem() {
log.info("Initializing actor system.");
actorContext.setActorService(this);
TbActorSystemSettings settings = new TbActorSystemSettings(actorThroughput, schedulerPoolSize, maxActorInitAttempts);
system = new DefaultTbActorSystem(settings);
//创建不同actor执行的线程池
system.createDispatcher(APP_DISPATCHER_NAME, initDispatcherExecutor(APP_DISPATCHER_NAME, appDispatcherSize));
system.createDispatcher(TENANT_DISPATCHER_NAME, initDispatcherExecutor(TENANT_DISPATCHER_NAME, tenantDispatcherSize));
system.createDispatcher(DEVICE_DISPATCHER_NAME, initDispatcherExecutor(DEVICE_DISPATCHER_NAME, deviceDispatcherSize));
system.createDispatcher(RULE_DISPATCHER_NAME, initDispatcherExecutor(RULE_DISPATCHER_NAME, ruleDispatcherSize));
actorContext.setActorSystem(system);
//创建AppActor详细分析见①createActor分析
appActor = system.createRootActor(APP_DISPATCHER_NAME, new AppActor.ActorCreator(actorContext));
actorContext.setAppActor(appActor);
//创建statsActor,暂时不关注
TbActorRef statsActor = system.createRootActor(TENANT_DISPATCHER_NAME, new StatsActor.ActorCreator(actorContext, "StatsActor"));
actorContext.setStatsActor(statsActor);
log.info("Actor system initialized.");
}
①DefaultTbActorSystem
类中方法createActor
分析
private TbActorRef createActor(String dispatcherId, TbActorCreator creator, TbActorId parent) {
//获取initActorSystem时对应的线程池
Dispatcher dispatcher = dispatchers.get(dispatcherId);
if (dispatcher == null) {
log.warn("Dispatcher with id [{}] is not registered!", dispatcherId);
throw new RuntimeException("Dispatcher with id [" + dispatcherId + "] is not registered!");
}
//creator有不同的实现如AppActor,TenantActor,RuleChainActor, RuleNodeActor等
// AppActor, 则使用固定的NULL_UUID,UUID.fromString("13814000-1dd2-11b2-8080-808080808080")作为Id
// TenantActor 使用creator提供的tenantId作为Id
// RuleChainActor 使用creator提供的ruleChain作为Id
// RuleNodeActor 使用creator提供的ruleNodeId作为Id
TbActorId actorId = creator.createActorId();
//缓存使用,将已经创建的放入缓存
TbActorMailbox actorMailbox = actors.get(actorId);
if (actorMailbox != null) {
log.debug("Actor with id [{}] is already registered!", actorId);
} else {
Lock actorCreationLock = actorCreationLocks.computeIfAbsent(actorId, id -> new ReentrantLock());
actorCreationLock.lock();
try {
actorMailbox = actors.get(actorId);
if (actorMailbox == null) {
log.debug("Creating actor with id [{}]!", actorId);
//正式创建Actor,也就是调用构造函数
TbActor actor = creator.createActor();
//只允许AppActor的parent是空
TbActorRef parentRef = null;
if (parent != null) {
parentRef = getActor(parent);
if (parentRef == null) {
throw new TbActorNotRegisteredException(parent, "Parent Actor with id [" + parent + "] is not registered!");
}
}
//使用actor创建TbActorMailbox对象
TbActorMailbox mailbox = new TbActorMailbox(this, settings, actorId, parentRef, actor, dispatcher);
//放入缓存
actors.put(actorId, mailbox);
//用各自的线程池去进行初始化操作,具体的初始化操作由每种actor的init方法实现详细分析如下②③④
mailbox.initActor();
actorMailbox = mailbox;
if (parent != null) {
//缓存,父子关系缓存
parentChildMap.computeIfAbsent(parent, id -> ConcurrentHashMap.newKeySet()).add(actorId);
}
} else {
log.debug("Actor with id [{}] is already registered!", actorId);
}
} finally {
actorCreationLock.unlock();
actorCreationLocks.remove(actorId);
}
}
return actorMailbox;
}
-
②
TenantActor
的init
方法:如果此应用不是以某一个tennant启动的话或者
isolatedTbRuleEngine
是false,调用父类RuleChainManagerActor
的initRuleChains()
方法查询该租户下的rule_chain表。开始创建RuleChainActor
, 创建RuleChainActor
的parent是当前TenantActor
,创建的时候,又会调用到DefaultTbActorSystem
的createActor
方法; -
③
RuleChainActor
实现了ComponentActor
,ComponentActor
的init
方法调用了createProcessor(TbActorCtx ctx)
(由子类实现,创建了RuleChainActorMessageProcessor
实例)和initProcessor(TbActorCtx ctx)
(调用processor.start
也即RuleChainActorMessageProcessor
的start
方法,该方法查询查询relation表,条件为RULE_CHAIN和ruleChainId,再根据to_id去rule_node表获取RuleNode
;1. 根据ruleNodeList开始初创建RuleNodeActor
2.initRoutes()
查询relation,rule_node,rule_chain表,构造nodeRoutes的数据,并设置firstRuleNode); -
④
RuleNodeActor
实现了ComponentActor
,ComponentActor
的init
方法调用了createProcessor(TbActorCtx ctx)
(由子类实现,创建了RuleNodeActorMessageProcessor
实例)和initProcessor(TbActorCtx ctx)
, (调用processor.start
也即RuleNodeActorMessageProcessor
的start
方法,使用反射创建ruleNode的实例,并按照数据库configuration的配置,调用init
方法);
DefaultActorService
中@EventListener(ApplicationReadyEvent.class)
标记的onApplicationEvent
开始进一步初始化流程:
调用appActor.tellWithHighPriority(new AppInitMsg());
将AppInitMsg
推入AppActor
的消息队列里,然后尝试处理这一消息,最终会交给AppActor
的doProcess
方法进行处理,由于还未ruleChainsInitialized
从未进行复制,此时AppActor开始初始化TennatActor,查询tenant
表对所有tenant创建TenantActor
;
总结
-
initActorSystem
创建AppActor
和StatsActor
两个Actor,并未创建其他的Actor; -
在收到
ApplicationReadyEvent
的时候,由于之前没有初始化,所以会初始化该应用的所有TenantActor
, 根据②③④点分析,循环切递归的创建了所有的RuleChainActor
,RuleNodeActor
; -
关于
TbActorMailbox
的理解:mailbox理解为一个信箱,里面有一些信件(即入队列的消息),这些信件有一些是高优先级,有些是普通优先级的,每次取信件的时候,都先看有没高优先级的,先处理高优先级的信件,再处理普通优先级的信件。那么信件处理人是谁呢?信件的处理人就是每一个Actor.实际上的信件处理方法都是每一个Actor的doProcess(TbActorMsg msg)
方法; -
我们讨论的每一个
RuleNodeActor
就是在前端RULE CHAINS界面看到的每一个节点。