Skip to content

后端软件架构设计

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)

  1. 在线状态
    • 来源:EMQX Webhook 推送。
    • 存储:Redis SET device:{id}:online 1
    • 查询:直接读 Redis,速度极快。
  2. 属性状态 (影子)
    • 来源:设备主动上报 (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 接口)。