后端软件架构设计
1. 架构概览
后端服务基于 NestJS 框架构建,采用 模块化 (Modular) 架构。核心目标是实现高内聚、低耦合,并为未来的微服务拆分预留空间。
2. 模块划分 (Modules)
系统共划分为 5 个核心模块:
| 模块 | 职责 | 依赖服务 |
|---|---|---|
| CoreModule | 全局基础设置(Config, Logger, Database, Redis)。 | PrismaService, Redis |
| AuthModule | 处理用户登录、注册、JWT 签发与校验。 | UsersModule |
| UserModule | 用户增删改查、个人信息管理。 | PrismaService |
| ProductModule | 产品管理、物模型 (Thing Model) 的 CRUD。 | PrismaService |
| DeviceModule | 设备生命周期管理(注册、绑定、查询)、状态管理。 | PrismaService, Redis, MqttModule |
| MqttModule | 封装 MQTT 客户端,处理消息订阅、发布及指令路由。 | EMQX |
3. 核心业务流程实现
3.1 消息路由策略 (MqttService)
为了优雅地处理来自 MQTT 的海量消息,我们设计了一个基于 装饰器 (Decorator) 的路由机制,类似于 NestJS 的 Controller。
typescript
// 示例代码:使用装饰器订阅 Topic
@MqttController('sys')
export class DeviceEventController {
constructor(private readonly deviceService: DeviceService) {}
// 匹配 sys/+/+/thing/event/property/post
@SubscribeTopic('+/+/thing/event/property/post')
async handlePropertyPost(@Payload() payload: any, @Ctx() context: MqttContext) {
const { productId, deviceId } = context.getTopicParams();
await this.deviceService.updateShadow(deviceId, payload);
}
}3.2 设备状态管理 (DeviceService)
设备状态分为 实时状态 (Online/Offline) 和 属性状态 (Shadow)。
- 在线状态:
- 来源:EMQX Webhook 推送。
- 存储:Redis
SET device:{id}:online 1。 - 查询:直接读 Redis,速度极快。
- 属性状态 (影子):
- 来源:设备主动上报 (
property/post) 或 控制回复 (property/set_reply)。 - 存储:PostgreSQL
devices.shadow(JSONB) + InfluxDB (历史记录)。 - 策略:每次收到上报,先更新 PG 中的 shadow 字段(用于列表展示),再异步写入 InfluxDB(用于历史曲线)。
- 来源:设备主动上报 (
4. 目录结构规范
bash
src/
├── common/ # 通用组件 (过滤器, 守卫, 装饰器)
│ ├── decorators/
│ ├── filters/
│ └── guards/
├── config/ # 环境变量配置
├── modules/ # 业务模块
│ ├── auth/
│ ├── user/
│ ├── product/
│ ├── device/
│ └── mqtt/ # MQTT 封装与消息路由
├── shared/ # 共享服务 (Redis, Util)
└── main.ts # 入口文件5. 鉴权与安全
- API 鉴权:使用
Passport+JWT策略。所有/api/*接口(除登录注册)均需携带 Bearer Token。 - 设备鉴权:
- 设备连接 EMQX 时,使用
ClientId+Username+Password认证。 - EMQX 通过 HTTP 或者是内置数据库验证设备的合法性(初期可使用 EMQX 内置的 Password Based Auth,后期对接 NestJS 的 Auth 接口)。
- 设备连接 EMQX 时,使用
