第十部分:当前实现说明
10.1 技术基线
| 层 | 当前实现 | 职责 |
|---|---|---|
| 管理后台 | Vue 3、TypeScript、Vite、Pinia、Vue Router | 管理员和运维操作界面 |
| 用户端 | 原生微信小程序 | 用户登录、设备绑定、查看和控制 |
| 后端 | Java 17、Spring Boot 3.3、Spring Security、Spring Data JPA | 模块化单体业务 API |
| 业务数据库 | MySQL + Flyway | 用户、产品、设备、绑定、指令、告警和审计 |
| 登录与缓存 | Redis | 不透明登录 Token 验证、产品等热点缓存 |
| 设备消息 | Kafka | 后端唯一的设备消息订阅/发布入口 |
| MQTT | EMQX | 设备连接、ACL、MQTT Topic 与 Kafka 双向桥接 |
后端不引入 MQTT Client,也不直接订阅 EMQX。EMQX 负责 MQTT 会话,EMQX 规则/Bridge 将上行消息写入 Kafka;后端消费 Kafka。下行控制由后端写 Kafka,再由 EMQX Bridge 投递 MQTT。
10.2 工程结构
iot-platform-mvp/
├─ admin-web/ Vue 3 + TypeScript 管理后台
│ ├─ src/api API 封装
│ ├─ src/stores 登录状态
│ ├─ src/router 路由与角色守卫
│ ├─ src/layouts 后台布局
│ └─ src/views 总览、产品、设备、用户、指令、告警、审计
├─ backend/ Spring Boot 单体
│ ├─ src/main/java/.../api REST Controller 与统一响应
│ ├─ config Security、Redis Cache、种子数据
│ ├─ domain/repository JPA 实体与仓储
│ ├─ service 认证和设备业务用例
│ ├─ messaging Kafka 生产者/消费者及消息 DTO
│ └─ resources/db/migration Flyway MySQL 结构
└─ mini-program/ 原生微信小程序
10.3 单体模块边界
当前一个 Jar 内保留以下逻辑模块:
- IAM:后台账号、小程序账号、Redis 登录会话、RBAC。
- 产品/物模型:产品、协议和物模型版本。
- 设备:设备身份、绑定、在线状态、当前属性和遥测。
- 控制:指令入库、Kafka 下行、ACK 状态回写。
- 告警:设备事件转告警、告警处置。
- 审计:关键管理与用户操作留痕。
模块通过服务接口和 Kafka 事件 DTO 组织,不在首期过早拆分独立进程。
10.4 Kafka 与 EMQX 数据流
设备属性/事件
→ MQTT Topic
→ EMQX Rule/Bridge
→ iot.device.telemetry.up / iot.device.event.up
→ KafkaInboundListener
→ DeviceService
→ MySQL + Redis Cache
管理后台/小程序控制
→ Spring Boot API
→ device_command(PENDING)
→ iot.device.command.down
→ EMQX Bridge
→ MQTT 指令 Topic
→ 设备 ACK
→ iot.device.command.ack
→ device_command(SUCCEEDED/FAILED)
Topic 的 Key 统一为 deviceId,以保证单设备消息分区内有序。上行使用 messageId 幂等;下行使用 commandId 关联 ACK。
10.5 Redis 使用
- 后台或小程序登录成功后生成高熵不透明 Token。
- 会话写入
iot:session:{token},Value 保存用户 ID、用户名和角色,TTL 默认 24 小时。 - 每次 Bearer 请求由
TokenAuthenticationFilter查询 Redis 并恢复 Spring Security 身份。 - 产品列表使用 Spring Cache + Redis,默认 TTL 10 分钟;产品创建时清除缓存。
- 测试 profile 使用内存 SessionStore 和 Simple Cache,不访问真实 Redis。
后续可将设备在线 TTL、验证码限流、接口幂等键和短时设备影子热点加入 Redis,但业务事实仍以 MySQL/Kafka 为准。
10.6 MySQL 使用
当前 Flyway V1__init_schema.sql 创建:iam_user、iot_product、iot_device、device_telemetry、device_command、device_alert、audit_log。设备表使用乐观锁版本字段;遥测以 (device_id,message_id) 唯一约束去重。
初期遥测可保存在 MySQL 便于完成闭环。数据量达到容量阈值后,把遥测存储模块替换为专用时序方案,其他业务表仍留在 MySQL。
10.7 配置与启动
中间件地址不写入源码。字段清单见 backend/.env.example;收到实际地址文档后映射为部署环境变量。
# 后端测试与启动
cd iot-platform-mvp\backend
.\mvnw.cmd test
.\mvnw.cmd spring-boot:run
# 管理后台
cd ..\admin-web
npm install
npm run dev
- Spring Boot:
http://127.0.0.1:8080 - Vue 开发服务:
http://127.0.0.1:5173 - 小程序开发地址:
http://127.0.0.1:8080
10.8 测试与部署边界
自动测试使用 H2、内存登录会话和 Noop Kafka Publisher,验证单体业务、权限、绑定、遥测事件和指令状态,不依赖已部署中间件。收到地址与认证信息后还需执行 MySQL 迁移验证、Redis TTL/故障验证、Kafka Topic ACL 与收发验证、EMQX 双向 Bridge 验证和真实设备 ACK 联调。
10.9 微服务演进
满足以下任一条件再拆分:模块需要独立扩缩容、发布节奏明显不同、数据所有权稳定、单体发布影响无法接受。建议顺序:
- 先拆
device-ingestion(Kafka 上行、遥测、在线态),因为吞吐模型最不同。 - 再拆
device-command(指令、ACK、超时、Outbox)。 - 再按业务量拆
alert-service和iam-service。 - 产品/物模型与核心设备资产在边界稳定前保留一起。
拆分前先补 Transactional Outbox、契约测试、事件版本、可观测性和数据库归属,不以“类多了”作为拆服务理由。