Files
dashboard/.qoder/repowiki/zh/content/系统架构/后端架构.md
T
2026-06-30 14:46:52 +08:00

22 KiB
Raw Blame History

后端架构

**本文引用的文件** - [backend/src/app.js](file://backend/src/app.js) - [backend/package.json](file://backend/package.json) - [backend/src/config/env.js](file://backend/src/config/env.js) - [backend/src/config/database.js](file://backend/src/config/database.js) - [backend/src/config/redis.js](file://backend/src/config/redis.js) - [backend/src/config/logger.js](file://backend/src/config/logger.js) - [backend/src/routes/index.js](file://backend/src/routes/index.js) - [backend/src/middleware/auth.js](file://backend/src/middleware/auth.js) - [backend/src/middleware/bodyLimit.js](file://backend/src/middleware/bodyLimit.js) - [backend/src/utils/jwt.js](file://backend/src/utils/jwt.js) - [backend/src/utils/response.js](file://backend/src/utils/response.js) - [backend/src/routes/auth.js](file://backend/src/routes/auth.js) - [backend/src/services/userBootstrap.js](file://backend/src/services/userBootstrap.js) - [backend/src/models/DashboardUser.js](file://backend/src/models/DashboardUser.js) - [backend/src/models/index.js](file://backend/src/models/index.js) - [backend/src/services/curveClient.js](file://backend/src/services/curveClient.js) - [backend/src/services/eqCacheStorage.js](file://backend/src/services/eqCacheStorage.js) - [backend/src/services/measurementStorage.js](file://backend/src/services/measurementStorage.js)

目录

  1. 引言
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考虑
  8. 故障排查指南
  9. 结论
  10. 附录

引言

本文件面向后端架构与实现,围绕 Express 应用展开,系统性阐述 MVC 模式落地、中间件体系、路由组织、数据库连接、Redis 缓存、日志系统、认证授权、错误处理、请求限制、API 版本管理、安全防护与性能优化、启动流程、健康检查与监控配置等主题。文档同时提供可视化图示帮助读者快速把握代码结构与交互流程。

项目结构

后端采用模块化分层组织:

  • 配置层:环境变量、数据库、Redis、日志
  • 中间件层:认证、请求体大小限制
  • 路由层:按功能域划分的子路由集合
  • 服务层:业务逻辑封装(曲线拉取、EQ 缓存、频响存储等)
  • 工具层:JWT、密码、统一响应包装
  • 模型层:基于 Sequelize 的数据模型
  • 入口:应用启动与监听
graph TB
subgraph "入口"
APP["app.js<br/>启动与中间件注册"]
end
subgraph "配置"
ENV["env.js<br/>环境标识"]
DB["database.js<br/>Sequelize 实例"]
REDIS["redis.js<br/>Redis 客户端"]
LOG["logger.js<br/>Winston 日志"]
end
subgraph "中间件"
AUTHMW["auth.js<br/>认证/鉴权"]
BODYLIMIT["bodyLimit.js<br/>请求体大小限制"]
end
subgraph "路由"
ROUTESIDX["routes/index.js<br/>路由聚合"]
ROUTE_AUTH["routes/auth.js<br/>认证相关"]
end
subgraph "服务"
BOOTSTRAP["userBootstrap.js<br/>超级管理员初始化"]
CURVE["curveClient.js<br/>曲线拉取与校验"]
EQ["eqCacheStorage.js<br/>EQ 缓存读取"]
MEAS["measurementStorage.js<br/>频响文件 S3 存取"]
end
subgraph "模型"
MODELSIDX["models/index.js<br/>模型导出"]
MODEL_USER["DashboardUser.js<br/>用户模型"]
end
subgraph "工具"
JWT["jwt.js<br/>JWT 生成/解析"]
RESP["response.js<br/>统一响应包装"]
end
APP --> ENV
APP --> DB
APP --> REDIS
APP --> LOG
APP --> ROUTESIDX
APP --> AUTHMW
APP --> BODYLIMIT
ROUTESIDX --> ROUTE_AUTH
ROUTE_AUTH --> MODEL_USER
BOOTSTRAP --> MODEL_USER
EQ --> REDIS
MEAS --> DB
CURVE --> LOG
EQ --> LOG
MEAS --> LOG
JWT --> LOG

图表来源

章节来源

核心组件

  • 应用入口与中间件
    • 注册 CORS、JSON 解析、URL 编码解析、请求体大小限制中间件
    • 提供根路径与健康检查接口
    • 聚合并挂载各业务路由
  • 数据库连接
    • 基于 Sequelize 连接 MySQL,开发环境开启 SQL 日志输出
    • 应用启动时尝试同步数据库表结构
  • Redis 缓存
    • 单例客户端,支持密码、超时、重试次数配置
    • EQ 缓存采用 Redis Hash 结构,提供字段级读取与键列表查询
  • 日志系统
    • Winston 控制台与文件双通道输出,统一时间戳与格式化
  • 认证与授权
    • Bearer Token 解析与校验,支持超级管理员强制校验
  • 请求限制
    • 基于 Content-Length 的请求体大小限制(默认 8MB)

章节来源

架构总览

下图展示从请求进入至业务处理的关键流程,包括认证、路由分发、模型访问与外部服务调用。

sequenceDiagram
participant C as "客户端"
participant A as "Express 应用(app.js)"
participant M1 as "认证中间件(auth.js)"
participant R as "路由(auth.js)"
participant U as "工具(jwt.js/response.js)"
participant DB as "数据库(Sequelize)"
participant L as "日志(Winston)"
C->>A : "HTTP 请求"
A->>M1 : "执行认证中间件"
M1-->>A : "通过/拒绝"
A->>R : "路由分发"
R->>U : "生成响应/解析令牌"
R->>DB : "查询/更新用户"
DB-->>R : "结果"
R-->>C : "统一响应"
R->>L : "记录日志"

图表来源

详细组件分析

MVC 模式实现

  • 视图层
    • 本项目为 API 服务,无传统视图层;统一以 JSON 响应输出
  • 模型层
    • 使用 Sequelize 定义数据模型,集中于 models 目录,导出统一索引
    • 示例:DashboardUser 模型定义了用户字段、注释与表名
  • 控制器层
    • Express 路由作为控制器,负责接收请求、调用服务/模型、返回响应
    • 示例:认证路由处理登录、获取当前用户、修改密码
classDiagram
class DashboardUser {
+id : number
+username : string
+password_hash : string
+is_super_admin : number
+status : number
+last_login_at : date
+create_at : date
+update_at : date
}
class AuthRoute {
+login()
+getCurrentUser()
+changePassword()
}
AuthRoute --> DashboardUser : "读写"

图表来源

章节来源

中间件体系

  • 认证中间件
    • 从 Authorization 头提取 Bearer Token,解码并注入用户上下文
    • 支持超级管理员强制校验
  • 请求体大小限制
    • 基于 Content-Length 校验,超过阈值返回 413
flowchart TD
Start(["进入中间件"]) --> CheckAuth["检查 Authorization 头"]
CheckAuth --> HasToken{"存在 Bearer Token?"}
HasToken --> |否| Reject401["返回 401 未登录"]
HasToken --> |是| Verify["验证 Token"]
Verify --> Valid{"有效?"}
Valid --> |否| Reject401
Valid --> |是| InjectUser["注入用户上下文"]
InjectUser --> Next["放行"]
Reject401 --> End(["结束"])
Next --> End

图表来源

章节来源

路由组织结构

  • 路由聚合
    • routes/index.js 导出所有业务路由数组,入口统一挂载
  • 认证路由
    • 登录:校验凭据、更新最近登录时间、签发访问令牌
    • 获取当前用户:基于已认证用户 ID 查询
    • 修改密码:旧密码校验、新密码长度校验、更新哈希
sequenceDiagram
participant C as "客户端"
participant R as "认证路由(auth.js)"
participant DB as "数据库"
participant JWT as "JWT 工具"
participant RESP as "响应包装"
C->>R : "POST /api/auth/login"
R->>DB : "按用户名查询用户"
DB-->>R : "用户记录"
R->>R : "校验密码/状态"
R->>DB : "更新最近登录时间"
R->>JWT : "签发访问令牌"
R->>RESP : "构造成功响应"
R-->>C : "返回 access_token 与用户信息"

图表来源

章节来源

数据库连接管理

  • 连接配置
    • 通过环境变量配置主机、端口、用户名、密码、数据库名
    • 开发环境启用 SQL 日志,生产关闭
  • 启动同步
    • 应用启动时尝试同步表结构,失败记录告警但不阻断启动
  • 用户模型
    • 字段覆盖登录账号、密码哈希、状态、超级管理员标记、时间戳
flowchart TD
Boot(["应用启动"]) --> Sync["sequelize.sync()"]
Sync --> Ok{"同步成功?"}
Ok --> |是| Ready["记录成功日志"]
Ok --> |否| Warn["记录错误日志并继续"]
Ready --> Listen["监听端口"]
Warn --> Listen

图表来源

章节来源

Redis 缓存策略

  • 客户端
    • 单例懒加载,支持密码、超时、重试次数
  • EQ 缓存
    • 使用 Redis Hash 存储型号的 EQ 字段
    • 提供字段键列表查询与单字段读取
    • 读取失败统一抛错并记录日志
sequenceDiagram
participant S as "服务(eqCacheStorage.js)"
participant RC as "Redis 客户端(redis.js)"
participant L as "日志(logger.js)"
S->>RC : "hkeys(key)/hget(key, field)"
alt "键存在"
RC-->>S : "字段列表/字段值"
S-->>S : "解析 JSON 或原始值"
else "键不存在/读取异常"
RC-->>S : "null 或抛错"
S->>L : "记录错误日志"
S-->>S : "抛出统一错误"
end

图表来源

章节来源

日志系统配置

  • 输出目标
    • 控制台与文件双通道
  • 格式化
    • 时间戳、级别、消息、附加元数据
  • 目录
    • 自动创建 logs 目录

章节来源

认证授权机制

  • 令牌签发
    • 基于 HS256 算法,有效期 12 小时
  • 令牌解析
    • 校验失败按类型返回不同错误
  • 授权
    • 超级管理员强制校验,非管理员返回 403
flowchart TD
A["收到请求"] --> B["解析 Authorization 头"]
B --> C{"Bearer Token 存在?"}
C --> |否| E["返回 401 未登录"]
C --> |是| D["jwt.verify 校验"]
D --> F{"有效?"}
F --> |否| G["返回 401 无效凭证/过期"]
F --> |是| H["注入用户上下文"]
H --> I{"是否超级管理员?"}
I --> |否| J["返回 403"]
I --> |是| K["放行"]

图表来源

章节来源

错误处理与统一响应

  • 统一响应包装
    • 成功/错误/无数据三类包装对象
  • 路由层错误捕获
    • 认证路由对异常进行日志记录并返回统一错误响应
  • 外部服务错误
    • S3/曲线服务捕获异常并记录日志,抛出统一错误

章节来源

请求限制策略

  • 限制规则
    • 基于 Content-Length,超过 8MB 返回 413
  • 生效范围
    • 全局中间件,适用于所有路由

章节来源

API 版本管理

  • 当前实现
    • 路由路径采用 /api/{resource} 形态,未显式引入版本前缀
  • 建议
    • 可在入口处增加 /api/v1 前缀,后续迁移至 v2 时保持向后兼容

章节来源

安全防护

  • CORS
    • 允许任意来源与凭据
  • 认证
    • Bearer Token,建议配合 HTTPS 与短令牌有效期
  • 密码
    • 使用哈希存储,路由层对新密码长度进行约束
  • 请求限制
    • 8MB 限制,防止恶意大包

章节来源

性能优化方案

  • 数据库
    • 生产关闭 SQL 日志,减少 IO
    • 合理索引与查询条件,避免 N+1
  • 缓存
    • Redis Hash 结构降低网络往返
    • 字段键列表查询避免一次性传输大量数据
  • 外部服务
    • S3 与曲线接口设置合理超时与错误重试
  • 日志
    • 控制台与文件双通道,避免过多 info 级日志影响性能

章节来源

启动流程、健康检查与监控

  • 启动流程
    • 加载环境变量 → 初始化数据库 → 创建超级管理员 → 启动 HTTP 服务器
  • 健康检查
    • /health 返回健康状态
  • 监控建议
    • 结合日志与外部 APM 工具,关注慢查询、缓存命中率与外部接口延迟
sequenceDiagram
participant Boot as "启动脚本"
participant App as "app.js"
participant DB as "database.js"
participant Redis as "redis.js"
participant Logger as "logger.js"
Boot->>App : "node src/app.js"
App->>DB : "sequelize.sync()"
App->>App : "ensureBootstrapSuperAdmin()"
App->>Redis : "初始化客户端"
App->>Logger : "记录启动日志"
App->>App : "listen(PORT)"

图表来源

章节来源

依赖关系分析

  • 包管理与运行
    • 依赖 express、sequelize、mysql2、jsonwebtoken、winston、ioredis 等
    • 启动脚本使用 node 或 nodemon dev
  • 内部依赖
    • app.js 依赖配置、路由、中间件与引导服务
    • 路由依赖模型与工具
    • 服务依赖配置与日志
graph LR
P["package.json"] --> E["express"]
P --> S["sequelize"]
P --> M["mysql2"]
P --> J["jsonwebtoken"]
P --> W["winston"]
P --> R["ioredis"]
APP["app.js"] --> CFG["config/*"]
APP --> RT["routes/*"]
APP --> MW["middleware/*"]
APP --> SVC["services/*"]
RT --> MOD["models/*"]
RT --> UT["utils/*"]
SVC --> CFG
SVC --> LOG["logger.js"]

图表来源

章节来源

性能考虑

  • 数据库层
    • 生产关闭 SQL 日志,避免频繁 I/O
    • 合理使用索引与分页
  • 缓存层
    • Redis Hash 结构适合字段级访问
    • 仅读取字段键列表,避免大对象传输
  • 外部接口
    • 设置超时与错误处理,避免阻塞请求
  • 日志
    • 控制台与文件双通道,避免 info 级日志过多

故障排查指南

  • 认证失败
    • 检查 Authorization 头格式与令牌有效性
    • 查看日志定位具体错误原因
  • 数据库同步失败
    • 检查数据库连接参数与权限
    • 关注启动阶段的日志告警
  • Redis 读取异常
    • 检查 Redis 连接参数与网络连通性
    • 关注错误日志中的具体异常信息
  • S3 读取/上传失败
    • 检查凭证或 IAM 角色配置
    • 关注 NoSuchKey 等特定异常

章节来源

结论

本后端以 Express 为核心,采用清晰的分层与模块化设计,结合 Sequelize、Redis 与 Winston 实现了稳定的数据访问、缓存与日志能力。认证授权、请求限制与统一响应提升了安全性与一致性。建议后续引入 API 版本前缀、完善错误分类与指标上报,持续优化数据库与缓存策略以提升整体性能与可观测性。

附录

  • 环境变量
    • APP_ENVdevelopment/production
    • DATABASE_*:主机、端口、用户名、密码、数据库名
    • REDIS_*:主机、端口、密码、DB
    • JWT_SECRET:令牌签名密钥
    • DASHBOARD_ADMIN_*:超级管理员初始化用户名与密码
    • AWS_*S3 区域、凭证与桶名
  • 路由示例
    • GET / → 根路径
    • GET /health → 健康检查
    • POST /api/auth/login → 登录
    • GET /api/auth/me → 获取当前用户
    • PUT /api/auth/password → 修改密码

章节来源