ThingsBoard 的 Actor 系统如何初始化
正文与配图来自原稿。接 Actor 模型:Actors 不是随便
new,而是通过 ActorSystem 创建;本文看 TB 启动时如何把系统拉起来。
1、概述
ThingsBoard 使用 Actor 减轻多线程共享状态问题。Actor 通过 ActorSystem 创建。下面跟随启动流程看 Actor 如何初始化。
2、ThingsBoard 的 Actor 分类
源码中可见多种 Actor,例如:

常见包括:
| Actor | 从类名可理解的职责方向 |
|---|---|
| AppActor | 应用根 Actor |
| DeviceActor | 设备相关 |
| RuleChainActor | 规则链 |
| RuleNodeActor | 规则节点 |
| StatsActor | 统计 |
| TenantActor | 租户 |
具体行为以各类源码为准。
3、接口:TbActorSystem
系统侧定义接口 TbActorSystem,抽象 Actor 体系常用能力(创建 Actor、Dispatcher 等):

4、默认实现:DefaultTbActorSystem
DefaultTbActorSystem 实现上述接口。内部用若干 ConcurrentHashMap 保存 ActorId、Mailbox、Dispatcher 等映射:

5、上下文:ActorSystemContext
初始化需要上下文 ActorSystemContext:一般由 Spring 创建 Bean,注入大量 Service / 组件,并带上 yml 中的配置项,供各 Actor 调业务能力:

6、初始化入口:DefaultActorService
程序启动时,Actor 初始化从 DefaultActorService 开始:

其中 initActorSystem() 带 @PostConstruct。Spring Bean 生命周期大致为:
构造方法 → @Autowired 依赖注入 → @PostConstruct接着创建 TbActorSystemSettings(线程池、Actor 初始化重试次数等):

创建 Actor 系统:
system = new DefaultTbActorSystem(settings);再用该 system 创建 Dispatcher(分配器):

跟进 createDispatcher:把 dispatcherId 与 Dispatcher 放入 map;Dispatcher 持有 executor(可理解为执行线程池):

然后创建两个根 Actor:appActor 与 statsActor:

注意:这里拿到的通常是 TbActorRef,并不是直接 new AppActor() / new StatsActor() 的裸对象。创建时传入例如:
new AppActor.ActorCreator(actorContext)new StatsActor.ActorCreator(actorContext, "StatsActor")
再把这两个 Actor 引用设回 ActorSystemContext,方便后续使用。至此系统骨架已起来。
进入:
appActor = system.createRootActor(
APP_DISPATCHER_NAME,
new AppActor.ActorCreator(actorContext)
);最终落到 DefaultTbActorSystem#createActor:创建 TbActorMailbox,并与 actorId 一并放入 map:

调用 mailbox.initActor() → TbActorMailbox#initActor:

此处的 dispatcher 来自构造:
new TbActorMailbox(this, settings, actorId, parentRef, actor, dispatcher);再 tryInit(1)(尝试初始化一次),核心是:
actor.init(this);即初始化具体 Actor(如 AppActor),把 TbActorCtx 赋上。传入的 this 是当前 TbActorMailbox,而 Mailbox 实现了 TbActorCtx:


statsActor 的初始化路径同理。
补充(辅)
DefaultActorService.@PostConstruct
→ new DefaultTbActorSystem(settings)
→ createDispatcher(...)
→ createRootActor(AppActor / StatsActor)
→ createActor → TbActorMailbox
→ mailbox.initActor → actor.init(mailbox as TbActorCtx)- 设备上线、规则链加载等会在后续由 App/Tenant 等 Actor 按消息再创建子 Actor,不单在启动时全部
new完。 - 读源码时以你分支的包名为准(
org.thingsboard.server.actors一带)。
