2. ThingsBoard架构总览
ThingsBoard 从部署形态上分为两种:单体(Monolithic)与微服务(Microservices)。二者共用同一套核心业务逻辑,差别在于进程边界、通信方式与扩展粒度。理解这一点,是后续做容量规划、选型和排障的基础。
一、单体与微服务:同一内核,两种进程边界
单体模式下,所有模块(设备接入、规则引擎、告警、REST API、UI 后端)运行在同一个 JVM 进程内,模块之间是方法调用,没有网络开销。微服务模式下,这些模块被拆成独立服务,各自独立进程、独立部署,模块之间通过消息队列或gRPC通信。
关键差异不在功能,而在三处:通信成本(本地调用 vs 网络+序列化)、扩展粒度(整体扩容 vs 按服务扩容)、故障域(一处 OOM 拖垮全部 vs 单服务隔离)。单体适合中小规模、快速验证;微服务适合大规模设备接入、需要按接入/规则/存储分别扩容的场景。
二、核心模块划分
无论哪种形态,ThingsBoard 的功能都落在以下模块中,微服务只是把它们拆成独立进程:
- tb-transport:设备接入层,负责 MQTT、HTTP、CoAP、LwM2M 协议解析与设备认证,把上行数据转成统一内部消息。
- tb-core:设备、资产、租户、客户、关系等实体的管理与查询,是元数据中心。
- tb-rule-engine:规则链执行引擎,基于 Actor 模型,每个规则节点是一个 Actor,消息在节点间流转。
- tb-web-ui / tb-js-executor:前端界面与 JS 脚本执行器(规则节点中的自定义脚本在此运行)。
- tb-node(单体):上述模块合并为一个可执行 jar,通过配置开关决定启用哪些组件。
模块划分的核心原则是按数据流方向分层:接入层只做协议转换与鉴权,不碰业务规则;规则引擎只做消息处理,不直接访问设备元数据(通过 tb-core 的 RPC 获取);存储层按读写特征分离。
三、消息队列与数据库选型
消息队列在单体中可选,在微服务中必需。ThingsBoard 支持 Kafka、RabbitMQ、AWS SQS 等,生产环境首选 Kafka,原因是分区有序、可重放、高吞吐。选型时关注三点:
- 分区数:决定规则引擎并行度。分区数应 ≥ 规则引擎实例数,否则部分实例空闲。
- 副本因子:生产环境至少 3,保证 broker 故障不丢消息。
- 保留策略:按时间或大小,避免磁盘无限增长。
数据库分两类:关系型(PostgreSQL)存实体元数据、租户、规则链定义;时序型(Cassandra 或 PostgreSQL+TimescaleDB)存遥测数据。选型判断依据是写入速率与查询模式:
| 存储 | 适用场景 | 关键参数示例 |
|---|---|---|
| PostgreSQL | 中小规模、实体关系复杂、需要事务 | 连接池 20~50,shared_buffers 25% 内存 |
| Cassandra | 高写入吞吐、时序数据、多节点线性扩展 | 副本因子 3,一致性 QUORUM |
| Redis | 缓存设备状态、会话、规则引擎中间状态 | maxmemory-policy allkeys-lru |
四、水平扩展与高可用设计原则
水平扩展的前提是无状态化。ThingsBoard 的 tb-core、tb-rule-engine、tb-transport 都是无状态服务,可以任意增加实例,通过 Kafka 分区或负载均衡分发请求。有状态的部分只有数据库和消息队列,它们靠自身集群机制保证高可用。
具体扩展策略:
- 接入层扩展:增加 tb-transport 实例,前置负载均衡(如 HAProxy/Nginx)按连接数分发。MQTT 长连接需注意会话保持。
- 规则引擎扩展:增加 tb-rule-engine 实例,Kafka 分区自动重新分配,每个分区同一时刻只被一个实例消费,保证消息不重复处理。
- 数据库扩展:PostgreSQL 读写分离或分库;Cassandra 增加节点自动再平衡。
- 高可用:每个服务至少 2 实例,跨可用区部署;Kafka 副本因子 ≥ 3;数据库主从+自动故障转移。
一个可参考的容量估算示例(假设值,非实测):若单设备平均 1 条/秒遥测,10 万设备即 10 万条/秒。按 Kafka 单分区约 1~2 万条/秒估算,至少需要 6~10 个分区;若每个规则引擎实例处理 2 个分区,则需 3~5 个实例。实际值需压测确认,此处仅作规划起点。
总结:单体与微服务的选择取决于规模与运维能力;核心模块按数据流分层;消息队列在微服务中不可省略,Kafka 是首选;数据库按元数据与时序数据分离选型;水平扩展的前提是无状态化与分区数匹配,高可用靠多实例、多副本、跨区部署共同保证。