3、核心服务拆分:Transport服务、Rule Engine服务、Web UI服务、Entity服务
好,咱们进入正题。微服务架构改造,最核心的一步就是「拆」。
ThingsBoard 原本是个单体应用,所有功能揉在一起。你想想看,设备连接、规则处理、数据存储、前端展示……全在一个进程里跑。出了问题,整个系统都得重启。我早期在做一个智慧城市项目时,就吃过这个亏——设备量一上来,规则引擎卡死,连带着所有设备都掉线了。
所以,拆分是必须的。今天咱们重点聊四个核心服务:Transport、Rule Engine、Web UI、Entity。
3.1 Transport 服务:设备的「守门员」
Transport 服务,说白了就是负责跟设备打交道的那一层。它处理各种协议——MQTT、HTTP、CoAP、LwM2M……设备发来的数据,先经过它,再转发到后端。
为什么要单独拆出来?
因为设备连接是 IO 密集型的。一个网关可能同时管理上千个传感器,每个传感器每秒上报一次数据。如果跟业务逻辑混在一起,CPU 很快就扛不住了。
我个人的习惯是:Transport 服务只做三件事——
- 协议解析(把 MQTT 报文转成内部 JSON)
- 身份认证(检查设备 token 或证书)
- 数据转发(丢到 Kafka 或 RabbitMQ 里)
嗯,这里要注意:不要在 Transport 里做任何业务逻辑。比如「温度超过 50 度就报警」这种事,交给 Rule Engine 去做。Transport 只管收数据、传数据,越快越好。
核心原则:Transport 服务应该是无状态的。你可以随意水平扩展,加机器就能扛更多设备。
3.2 Rule Engine 服务:系统的「大脑」
Rule Engine 是 ThingsBoard 最核心的组件。它负责处理所有业务逻辑——数据过滤、告警触发、设备联动、数据持久化……
我在项目中遇到过一个问题:客户要求「当温度超过 60 度时,不仅要报警,还要自动关闭阀门」。这个逻辑如果用传统方式写死在代码里,每次改需求都得重新部署。但用 Rule Engine,你可以在界面上拖拽节点,改规则就像搭积木一样。
拆分后的架构变化:
| 维度 | 单体架构 | 微服务架构 |
|---|---|---|
| 规则执行 | 与主进程共享线程池 | 独立进程,独立线程池 |
| 资源隔离 | 规则卡死 → 全系统卡死 | 规则卡死 → 只影响规则引擎 |
| 扩展方式 | 只能纵向扩展 | 可横向扩展,按需加节点 |
| 部署频率 | 改规则需重启整个系统 | 规则热更新,无需重启 |
你想想看,如果规则引擎独立出来,你甚至可以给它分配独立的 CPU 和内存。我曾经在一个项目中,把 Rule Engine 的堆内存从 2G 调到 8G,规则处理速度直接翻了三倍。
避坑指南:我曾经犯过一个错误——把 Rule Engine 和 Transport 部署在同一台机器上。结果设备连接数一高,规则处理就变慢。后来我强制把它们分开部署,问题就解决了。记住:IO 密集和 CPU 密集的服务,不要混在一起。
3.3 Web UI 服务:用户的「眼睛」
Web UI 服务,就是咱们在浏览器里看到的那个界面。它负责展示仪表盘、设备列表、告警信息……
很多人觉得「前端有什么好拆的?不就是静态文件吗?」——其实不是。ThingsBoard 的 Web UI 是动态的,它需要从后端拉数据、实时刷新图表、处理 WebSocket 推送。
拆分的好处:
- 独立部署:前端更新不影响后端服务。我习惯用 Nginx 做反向代理,把静态资源缓存起来,加载速度飞快。
- 独立扩展:如果用户量大,可以给 Web UI 加 CDN,或者多部署几个 Nginx 实例。
- 技术栈解耦:前端用 Angular/React,后端用 Java/Spring,互不干扰。
嗯,这里有个小技巧:Web UI 服务应该只做「展示」。所有的数据聚合、权限校验,都交给后端 API 去做。前端只负责渲染,别掺和业务逻辑。
3.4 Entity 服务:数据的「管家」
Entity 服务,负责管理 ThingsBoard 里的所有「实体」——设备、资产、仪表盘、用户、租户……说白了,就是 CRUD 操作。
你可能会问:「CRUD 有什么好拆的?」——其实大有讲究。
我举个例子:在一个大型物联网平台中,可能有几十万个设备,每个设备有上百个属性。如果所有实体的读写都混在一起,数据库连接池很快就满了。而且,设备属性的读写频率远高于仪表盘配置的读写频率,把它们分开,可以针对性地优化。
Entity 服务的拆分策略:
| 子服务 | 职责 | 典型操作 |
|---|---|---|
| Device Service | 设备注册、属性管理 | 创建设备、更新属性、查询设备列表 |
| Asset Service | 资产管理 | 创建资产、关联设备 |
| Dashboard Service | 仪表盘配置 | 保存仪表盘、分享仪表盘 |
| User Service | 用户与权限 | 用户注册、角色分配、权限校验 |
我个人建议:Entity 服务最好用独立的数据库。比如 Device Service 用 Cassandra,User Service 用 PostgreSQL。这样即使某个数据库挂了,其他服务还能正常运行。
注意:Entity 服务之间可能会有依赖关系。比如创建设备时需要校验用户权限。这时候不要直接调用对方的 API,而是通过消息队列异步处理,或者用 API Gateway 做聚合。
3.5 服务拆分的「黄金法则」
讲了这么多,最后总结几条我自己的经验:
- 按「变化频率」拆分:经常变的服务(如 Rule Engine)和很少变的服务(如 Entity)分开。
- 按「资源需求」拆分:IO 密集(Transport)和 CPU 密集(Rule Engine)分开。
- 按「团队边界」拆分:如果团队大,每个服务由不同小组维护。
- 不要拆得太细:我见过有人把每个 CRUD 都拆成一个服务,结果部署了 50 个微服务,运维直接崩溃。适度拆分,够用就好。
好了,这一章就到这里。下一章咱们聊聊「消息队列选型:Kafka vs RabbitMQ vs Pulsar」,到时候我会分享一些实际踩坑的经历。