4、集群架构:微服务架构拆解、消息队列选型(Kafka/RabbitMQ)、服务注册与发现
好,咱们进入第四章。这一章聊的是集群架构,说白了就是ThingsBoard怎么从单机跑成分布式。我见过不少团队,一开始图省事用单机部署,结果业务一上来就崩了。嗯,这里咱们得把微服务拆明白,把消息队列选对,再把服务发现搞定。
4.1 微服务架构拆解:从单体到分布式
ThingsBoard的微服务架构,我习惯把它拆成三层来看:
- 接入层:负责设备连接,处理MQTT、HTTP、CoAP等协议。这一层是无状态的,可以随便横向扩展。
- 业务层:处理规则引擎、告警、数据持久化等。这一层是有状态的,需要小心设计。
- 存储层:包括Cassandra/PostgreSQL、Kafka、Redis等。这一层是瓶颈所在,得重点优化。
具体到ThingsBoard的微服务模块,我列个表给你看:
| 模块名称 | 职责 | 状态 | 扩展方式 |
|---|---|---|---|
| tb-transport | 设备协议接入 | 无状态 | 直接加实例 |
| tb-rule-engine | 规则链处理 | 有状态 | 分区扩展 |
| tb-core | 核心业务逻辑 | 有状态 | 分片扩展 |
| tb-js-executor | JS脚本执行 | 无状态 | 直接加实例 |
| tb-web-ui | 前端服务 | 无状态 | 直接加实例 |
我在项目中遇到过一个问题:tb-rule-engine实例数加多了,反而导致规则链处理变慢。为什么?因为每个实例都要从Kafka拉取全量数据,竞争太激烈了。后来我们按租户ID做了分区,每个实例只处理特定分区的数据,问题就解决了。
核心原则:无状态服务随便扩,有状态服务要分区。别一股脑加实例,得看瓶颈在哪。
4.2 消息队列选型:Kafka vs RabbitMQ
消息队列是微服务架构的血管。ThingsBoard官方推荐Kafka,但我见过不少团队硬上RabbitMQ,结果踩坑。咱们客观对比一下:
| 特性 | Kafka | RabbitMQ |
|---|---|---|
| 吞吐量 | 百万级/秒 | 万级/秒 |
| 消息持久化 | 磁盘顺序写,性能高 | 内存+磁盘,有瓶颈 |
| 消息顺序 | 分区内严格有序 | 需要额外配置 |
| 消费模式 | 拉模式(Pull) | 推模式(Push) |
| 运维复杂度 | 较高,依赖ZooKeeper | 较低,自带管理界面 |
我个人习惯是:设备数据量大的场景,无脑选Kafka。你想想看,一个物联网平台每天处理几亿条数据,RabbitMQ的推模式很容易把消费者打爆。Kafka的拉模式让消费者自己控制速度,这才是正经的背压机制。
但也不是说RabbitMQ不能用。我记得有个项目,设备量不大(几千台),但业务逻辑复杂,需要灵活的路由和延迟队列。这时候RabbitMQ的交换机模型就很好用。说白了,选型要看场景:
- 高吞吐、日志型数据:Kafka
- 复杂路由、低延迟:RabbitMQ
- 两者都要:可以混用,Kafka做数据管道,RabbitMQ做业务消息
避坑指南:我曾经在Kafka的topic分区数上吃过亏。分区数太少,消费者组内竞争激烈;分区数太多,ZooKeeper压力大。经验值是:分区数 = 消费者实例数 × 2~3倍,留点余量。
4.3 服务注册与发现:Eureka vs Consul vs Nacos
微服务之间怎么找到对方?这就是服务注册与发现要解决的问题。ThingsBoard官方用的是Eureka,但我建议你根据实际情况选:
| 组件 | CAP模型 | 健康检查 | 配置管理 | 社区活跃度 |
|---|---|---|---|---|
| Eureka | AP(可用性优先) | 心跳机制 | 无 | 较低(Netflix维护) |
| Consul | CP(一致性优先) | 多种检查(HTTP/TCP/脚本) | 有(Key-Value) | 中等 |
| Nacos | AP+CP(动态切换) | 心跳+主动探测 | 有(动态配置) | 高(阿里维护) |
我个人的建议是:新项目优先考虑Nacos。为什么?因为它把服务发现和配置管理合二为一了,少维护一个组件。而且它的健康检查机制比Eureka更可靠——Eureka只靠心跳,网络抖动时容易误判;Nacos还支持主动探测,更准确。
但如果你已经在用Spring Cloud全家桶,Eureka也是个稳妥的选择。我记得有个老项目,从Eureka迁移到Nacos,花了整整两周改配置。嗯,迁移成本得算进去。
小技巧:不管用哪个组件,一定要配置多数据中心。我见过一个案例,单数据中心挂了,整个集群都找不到服务了。至少两个数据中心,异地容灾。
4.4 实战配置示例
最后,给一个ThingsBoard微服务架构的典型配置。假设我们用Kafka做消息队列,Nacos做服务发现:
# tb-core.yml 核心服务配置
server:
port: 8080
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.1.100:8848,192.168.1.101:8848
namespace: tb-prod
kafka:
bootstrap-servers: 192.168.1.200:9092,192.168.1.201:9092
topics:
telemetry: tb-telemetry
rule-engine: tb-rule-chain
consumer:
group-id: tb-core-group
auto-offset-reset: earliest
thingsboard:
cache:
type: redis
redis:
host: 192.168.1.300
port: 6379
cluster: true
这个配置里,我特别强调一下:Kafka的bootstrap-servers一定要配多个节点。我曾经只配了一个,结果那个节点挂了,整个集群都连不上Kafka。嗯,血的教训。
好了,这一章就到这里。下一章咱们聊聊数据存储的选型,Cassandra和PostgreSQL怎么选,什么时候用TimescaleDB。到时候见。