Files

404 lines
19 KiB
Markdown
Raw Permalink Normal View History

2026-06-30 14:46:52 +08:00
# 集成模式
<cite>
**本文档引用的文件**
- [backend/src/app.js](file://backend/src/app.js)
- [backend/src/config/env.js](file://backend/src/config/env.js)
- [backend/src/config/logger.js](file://backend/src/config/logger.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/middleware/auth.js](file://backend/src/middleware/auth.js)
- [backend/src/utils/jwt.js](file://backend/src/utils/jwt.js)
- [backend/src/services/curveClient.js](file://backend/src/services/curveClient.js)
- [backend/src/services/measurementStorage.js](file://backend/src/services/measurementStorage.js)
- [backend/src/services/eqCacheStorage.js](file://backend/src/services/eqCacheStorage.js)
- [backend/src/services/otaStorage.js](file://backend/src/services/otaStorage.js)
- [backend/src/routes/brands.js](file://backend/src/routes/brands.js)
- [backend/src/routes/models.js](file://backend/src/routes/models.js)
- [backend/src/routes/ota.js](file://backend/src/routes/ota.js)
- [backend/package.json](file://backend/package.json)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件系统性梳理后端服务与外部系统及组件的集成策略,覆盖日志系统、文件上传与对象存储、第三方 API 调用、微服务间通信与事件驱动、缓存层与数据库连接池、资源管理、集成测试、监控告警与故障转移、配置管理与版本兼容性等主题。目标是帮助开发者与运维人员快速理解系统的集成边界与运行机制,并提供可操作的优化建议与排障指引。
## 项目结构
后端采用 Express 应用入口集中加载中间件、路由与数据库初始化;配置模块按职责拆分,分别负责环境、日志、数据库与 Redis;服务层封装对外部系统的调用与存储逻辑;路由层统一鉴权并编排业务流程;工具与验证器模块提供通用能力。
```mermaid
graph TB
A["应用入口<br/>backend/src/app.js"] --> B["配置模块<br/>env.js / logger.js / database.js / redis.js"]
A --> C["中间件<br/>auth.js / bodyLimit.js"]
A --> D["路由模块<br/>brands.js / models.js / ota.js"]
D --> E["服务层<br/>curveClient.js / measurementStorage.js / eqCacheStorage.js / otaStorage.js"]
E --> F["外部系统<br/>Meilisearch / AWS S3 / Redis / 第三方曲线 API"]
B --> G["数据库<br/>MySQL(Sequelize)"]
```
图表来源
- [backend/src/app.js:1-60](file://backend/src/app.js#L1-L60)
- [backend/src/config/env.js:1-13](file://backend/src/config/env.js#L1-L13)
- [backend/src/config/logger.js:1-29](file://backend/src/config/logger.js#L1-L29)
- [backend/src/config/database.js:1-24](file://backend/src/config/database.js#L1-L24)
- [backend/src/config/redis.js:1-32](file://backend/src/config/redis.js#L1-L32)
- [backend/src/middleware/auth.js:1-36](file://backend/src/middleware/auth.js#L1-L36)
- [backend/src/routes/brands.js:1-147](file://backend/src/routes/brands.js#L1-L147)
- [backend/src/routes/models.js:1-569](file://backend/src/routes/models.js#L1-L569)
- [backend/src/routes/ota.js:1-292](file://backend/src/routes/ota.js#L1-L292)
- [backend/src/services/curveClient.js:1-147](file://backend/src/services/curveClient.js#L1-L147)
- [backend/src/services/measurementStorage.js:1-115](file://backend/src/services/measurementStorage.js#L1-L115)
- [backend/src/services/eqCacheStorage.js:1-73](file://backend/src/services/eqCacheStorage.js#L1-L73)
- [backend/src/services/otaStorage.js:1-113](file://backend/src/services/otaStorage.js#L1-L113)
章节来源
- [backend/src/app.js:1-60](file://backend/src/app.js#L1-L60)
## 核心组件
- 环境与配置:通过统一环境变量判断开发/生产,控制日志级别与数据库日志输出。
- 日志系统:基于 Winston 控制台与文件双通道输出,统一时间戳与结构化日志格式。
- 数据库:Sequelize 连接 MySQL,按环境启用 SQL 日志,冻结表名与关闭时间戳。
- 缓存:Redis 客户端按需懒加载,错误事件记录到日志。
- 鉴权:JWT 令牌解析与中间件拦截,支持超级管理员校验。
- 外部集成:Meilisearch 文档检索、AWS S3 对象存储、第三方曲线 API、OTA 包上传与本地落盘。
章节来源
- [backend/src/config/env.js:1-13](file://backend/src/config/env.js#L1-L13)
- [backend/src/config/logger.js:1-29](file://backend/src/config/logger.js#L1-L29)
- [backend/src/config/database.js:1-24](file://backend/src/config/database.js#L1-L24)
- [backend/src/config/redis.js:1-32](file://backend/src/config/redis.js#L1-L32)
- [backend/src/middleware/auth.js:1-36](file://backend/src/middleware/auth.js#L1-L36)
- [backend/src/utils/jwt.js:1-28](file://backend/src/utils/jwt.js#L1-L28)
## 架构总览
系统采用“HTTP API + 多外部系统”的集成架构:Express 提供 REST 接口,路由层统一鉴权与参数编排,服务层封装具体集成动作,配置层统一管理外部系统凭据与行为。
```mermaid
graph TB
subgraph "应用层"
R1["路由<br/>brands.js / models.js / ota.js"]
M1["中间件<br/>auth.js / bodyLimit.js"]
U1["工具<br/>jwt.js"]
end
subgraph "服务层"
S1["曲线服务<br/>curveClient.js"]
S2["频响存储<br/>measurementStorage.js"]
S3["缓存读取<br/>eqCacheStorage.js"]
S4["OTA 存储<br/>otaStorage.js"]
end
subgraph "外部系统"
E1["Meilisearch"]
E2["AWS S3"]
E3["Redis"]
E4["第三方曲线 API"]
end
R1 --> M1
R1 --> U1
R1 --> S1
R1 --> S2
R1 --> S3
R1 --> S4
S1 --> E4
S2 --> E2
S3 --> E3
R1 --> E1
```
图表来源
- [backend/src/routes/brands.js:1-147](file://backend/src/routes/brands.js#L1-L147)
- [backend/src/routes/models.js:1-569](file://backend/src/routes/models.js#L1-L569)
- [backend/src/routes/ota.js:1-292](file://backend/src/routes/ota.js#L1-L292)
- [backend/src/services/curveClient.js:1-147](file://backend/src/services/curveClient.js#L1-L147)
- [backend/src/services/measurementStorage.js:1-115](file://backend/src/services/measurementStorage.js#L1-L115)
- [backend/src/services/eqCacheStorage.js:1-73](file://backend/src/services/eqCacheStorage.js#L1-L73)
- [backend/src/services/otaStorage.js:1-113](file://backend/src/services/otaStorage.js#L1-L113)
## 详细组件分析
### 日志系统集成
- 输出介质:控制台与文件双通道,文件自动创建日志目录。
- 格式:时间戳、级别、消息与附加元数据 JSON 字符串化。
- 环境控制:开发环境开启数据库 SQL 日志,生产环境关闭以降低噪声。
- 使用场景:所有服务与路由均通过统一 logger 记录请求、响应与异常。
```mermaid
flowchart TD
Start(["请求进入"]) --> LogInfo["记录请求信息"]
LogInfo --> Process["业务处理"]
Process --> Ok{"处理成功?"}
Ok --> |是| LogOk["记录成功日志"]
Ok --> |否| LogErr["记录错误日志"]
LogOk --> End(["响应返回"])
LogErr --> End
```
图表来源
- [backend/src/config/logger.js:1-29](file://backend/src/config/logger.js#L1-L29)
- [backend/src/config/database.js:15](file://backend/src/config/database.js#L15)
章节来源
- [backend/src/config/logger.js:1-29](file://backend/src/config/logger.js#L1-L29)
- [backend/src/config/env.js:1-13](file://backend/src/config/env.js#L1-L13)
- [backend/src/config/database.js:1-24](file://backend/src/config/database.js#L1-L24)
### 文件上传与对象存储集成(S3)
- Meilisearch 集成:提供文档查询与删除能力,支持超时与 404 特判。
- S3 频响文件:根据品牌/型号/佩戴方式生成键值,支持凭证直连与 IAM 角色两种模式。
- 上传流程:路由接收 multipart/form-data,服务层转换 TXT→CSV 并上传至 S3。
- 读取流程:按模型来源与佩戴方式定位键值,返回 CSV 内容。
```mermaid
sequenceDiagram
participant C as "客户端"
participant R as "路由(models.js)"
participant S as "S3 服务(measurementStorage.js)"
participant A as "AWS S3"
C->>R : "POST /api/models/ (含 measurement_file)"
R->>R : "校验扩展名/转换TXT为CSV"
R->>S : "uploadMeasurementToS3(buffer, params)"
S->>A : "PutObjectCommand(Bucket, Key, Body)"
A-->>S : "返回结果"
S-->>R : "返回 S3 Key"
R-->>C : "返回上传结果"
```
图表来源
- [backend/src/routes/models.js:306-361](file://backend/src/routes/models.js#L306-L361)
- [backend/src/services/measurementStorage.js:61-80](file://backend/src/services/measurementStorage.js#L61-L80)
章节来源
- [backend/src/routes/models.js:1-569](file://backend/src/routes/models.js#L1-L569)
- [backend/src/services/measurementStorage.js:1-115](file://backend/src/services/measurementStorage.js#L1-L115)
### 第三方 API 调用模式(曲线 API)
- 目标:拉取并校验第三方曲线数据,支持自定义 Base64 映射与 parametric_eq 结构校验。
- 流程:构造查询参数 → 发起 HTTP 请求 → 提取编码数据 → Base64 解码 → JSON 校验 → 返回结果。
- 错误处理:对响应为空、格式异常、解码失败、JSON 非法、payload 异常进行分类处理并记录日志。
```mermaid
flowchart TD
A["输入: 品牌/型号/佩戴方式"] --> B["构造 URL 查询参数"]
B --> C["GET 曲线 API"]
C --> D{"HTTP 200"}
D --> |否| E["返回错误: HTTP 状态"]
D --> |是| F["提取编码数据"]
F --> G{"提取成功?"}
G --> |否| H["返回错误: 未找到可解码数据"]
G --> |是| I["自定义 Base64 解码"]
I --> J{"解码成功?"}
J --> |否| K["返回错误: Base64 解码失败"]
J --> |是| L["JSON 解析"]
L --> M{"JSON 合法且结构正确?"}
M --> |否| N["返回错误: 曲线数据异常"]
M --> |是| O["返回成功"]
```
图表来源
- [backend/src/services/curveClient.js:81-138](file://backend/src/services/curveClient.js#L81-L138)
章节来源
- [backend/src/services/curveClient.js:1-147](file://backend/src/services/curveClient.js#L1-L147)
### 缓存层集成(Redis
- 客户端:按需懒加载,支持密码、超时与重试次数配置,错误事件统一记录日志。
- 读取:提供哈希键集合与单字段读取,避免一次性返回过大响应体。
- 场景:EQ 缓存字段列表与单字段值读取,便于前端按需加载。
```mermaid
sequenceDiagram
participant R as "路由(models.js)"
participant S as "缓存服务(eqCacheStorage.js)"
participant RC as "Redis 客户端(config/redis.js)"
R->>S : "getEqCacheKeys(brand, model)"
S->>RC : "exists(redisKey)"
alt "存在"
S->>RC : "hkeys(redisKey)"
RC-->>S : "field 列表"
else "不存在"
S-->>R : "返回空字段"
end
R->>S : "getEqCacheField(brand, model, key)"
S->>RC : "hget(redisKey, key)"
RC-->>S : "value 或 null"
S-->>R : "返回解析后的值"
```
图表来源
- [backend/src/routes/models.js:183-223](file://backend/src/routes/models.js#L183-L223)
- [backend/src/services/eqCacheStorage.js:24-66](file://backend/src/services/eqCacheStorage.js#L24-L66)
- [backend/src/config/redis.js:11-29](file://backend/src/config/redis.js#L11-L29)
章节来源
- [backend/src/config/redis.js:1-32](file://backend/src/config/redis.js#L1-L32)
- [backend/src/services/eqCacheStorage.js:1-73](file://backend/src/services/eqCacheStorage.js#L1-L73)
- [backend/src/routes/models.js:183-223](file://backend/src/routes/models.js#L183-L223)
### 微服务间通信与事件驱动
- 当前实现:内部路由通过 Express 提供 REST 接口,未发现内置消息队列或事件总线代码。
- 建议:若未来引入异步任务或跨服务事件,可考虑引入消息队列(如 RabbitMQ/Kafka)与事件驱动架构,结合幂等与重试策略。
章节来源
- [backend/src/routes/brands.js:1-147](file://backend/src/routes/brands.js#L1-L147)
- [backend/src/routes/models.js:1-569](file://backend/src/routes/models.js#L1-L569)
- [backend/src/routes/ota.js:1-292](file://backend/src/routes/ota.js#L1-L292)
### 数据库连接池与资源管理
- 连接:Sequelize 连接 MySQL,开发环境打印 SQL,生产环境关闭。
- 表定义:冻结表名、关闭时间戳,减少迁移成本。
- 初始化:应用启动时尝试同步数据库表结构,失败记录警告并继续运行。
```mermaid
flowchart TD
A["启动应用(app.js)"] --> B["加载配置(database.js)"]
B --> C["创建 Sequelize 实例"]
C --> D{"开发环境?"}
D --> |是| E["开启 SQL 日志"]
D --> |否| F["关闭 SQL 日志"]
E --> G["同步数据库表结构"]
F --> G
G --> H["监听端口并启动服务"]
```
图表来源
- [backend/src/app.js:42-57](file://backend/src/app.js#L42-L57)
- [backend/src/config/database.js:14](file://backend/src/config/database.js#L14)
章节来源
- [backend/src/config/database.js:1-24](file://backend/src/config/database.js#L1-L24)
- [backend/src/app.js:1-60](file://backend/src/app.js#L1-L60)
### 鉴权与安全
- JWT:签发与解析使用固定密钥与算法,设置 12 小时有效期。
- 中间件:统一 Bearer Token 校验,支持超级管理员权限校验。
- 路由保护:多数业务路由挂载 auth 中间件,部分公开接口(如 OTA 最新版本检查)允许匿名访问。
```mermaid
sequenceDiagram
participant C as "客户端"
participant R as "路由(models.js/brands.js/ota.js)"
participant M as "鉴权中间件(auth.js)"
participant T as "JWT 工具(jwt.js)"
C->>R : "携带 Authorization : Bearer <token>"
R->>M : "校验头部格式"
M->>T : "decodeToken(token)"
T-->>M : "用户负载"
M-->>R : "注入 req.user"
R-->>C : "继续业务处理"
```
图表来源
- [backend/src/middleware/auth.js:3-26](file://backend/src/middleware/auth.js#L3-L26)
- [backend/src/utils/jwt.js:7-21](file://backend/src/utils/jwt.js#L7-L21)
- [backend/src/routes/models.js:70-71](file://backend/src/routes/models.js#L70-L71)
- [backend/src/routes/brands.js:11-12](file://backend/src/routes/brands.js#L11-L12)
- [backend/src/routes/ota.js:104-105](file://backend/src/routes/ota.js#L104-L105)
章节来源
- [backend/src/middleware/auth.js:1-36](file://backend/src/middleware/auth.js#L1-L36)
- [backend/src/utils/jwt.js:1-28](file://backend/src/utils/jwt.js#L1-L28)
- [backend/src/routes/models.js:1-569](file://backend/src/routes/models.js#L1-L569)
- [backend/src/routes/brands.js:1-147](file://backend/src/routes/brands.js#L1-L147)
- [backend/src/routes/ota.js:1-292](file://backend/src/routes/ota.js#L1-L292)
### OTA 升级包存储策略
- X8:上传至 S3,按年月/设备/MD5 前缀组织键值,返回公共下载地址。
- X9:保存到本地目录(开发/生产目录可配置),按年月/设备/MD5 前缀组织路径,返回公共 URL。
- 校验:计算 MD5 用于命名与去重。
```mermaid
flowchart TD
A["接收文件(Multer)"] --> B["计算 MD5"]
B --> C{"设备型号"}
C --> |X8| D["构建 S3 Key (年月/设备/MD5前缀)"]
D --> E["S3 上传"]
E --> F["返回下载地址与 Key"]
C --> |X9| G["构建本地路径 (年月/设备/MD5前缀)"]
G --> H["写入文件"]
H --> I["返回下载地址与文件名"]
```
图表来源
- [backend/src/routes/ota.js:24-66](file://backend/src/routes/ota.js#L24-L66)
- [backend/src/services/otaStorage.js:51-103](file://backend/src/services/otaStorage.js#L51-L103)
章节来源
- [backend/src/routes/ota.js:1-292](file://backend/src/routes/ota.js#L1-L292)
- [backend/src/services/otaStorage.js:1-113](file://backend/src/services/otaStorage.js#L1-L113)
### 配置管理、版本兼容与升级策略
- 环境变量:APP_ENV 控制开发/生产;数据库、S3、Redis、JWT 等均通过环境变量配置。
- 版本与依赖:后端使用 Node 生态主流库,S3 SDK 与 Winston 等均支持多版本共存,建议在 CI 中锁定版本并定期扫描安全漏洞。
- 升级策略:建议采用蓝绿/滚动发布,配合健康检查与回滚脚本;数据库变更通过迁移工具与只增不改策略降低风险。
章节来源
- [backend/src/config/env.js:1-13](file://backend/src/config/env.js#L1-L13)
- [backend/src/config/database.js:1-24](file://backend/src/config/database.js#L1-L24)
- [backend/src/config/redis.js:1-32](file://backend/src/config/redis.js#L1-L32)
- [backend/src/utils/jwt.js:3](file://backend/src/utils/jwt.js#L3)
- [backend/package.json:1-29](file://backend/package.json#L1-L29)
## 依赖关系分析
- 应用入口依赖配置模块与路由集合,路由依赖中间件与服务层,服务层依赖外部系统 SDK。
- 关键外部依赖:Express、Sequelize、Winston、Axios、AWS S3 Client、ioredis、jsonwebtoken。
```mermaid
graph LR
App["app.js"] --> Cfg["config/*"]
App --> Rt["routes/*"]
Rt --> Mid["middleware/*"]
Rt --> Svc["services/*"]
Svc --> Ext["外部系统 SDK"]
Ext --> Dep["package.json 依赖"]
```
图表来源
- [backend/src/app.js:1-60](file://backend/src/app.js#L1-L60)
- [backend/package.json:11-24](file://backend/package.json#L11-L24)
章节来源
- [backend/src/app.js:1-60](file://backend/src/app.js#L1-L60)
- [backend/package.json:1-29](file://backend/package.json#L1-L29)
## 性能考量
- 日志:生产关闭数据库 SQL 日志,避免 I/O 抖动;必要时将日志输出到集中式日志系统。
- 缓存:优先使用 Redis 哈希字段读取,避免一次性传输大对象;合理设置连接超时与重试。
- 存储:S3 上传使用内存流,注意文件大小限制与超时;对大文件可考虑分片上传。
- 数据库:批量写入与查询时使用分页与索引;避免 N+1 查询。
- API:对第三方曲线 API 设置合理超时与重试;对 Meilisearch 推送使用批量接口并限流。
## 故障排查指南
- 日志定位:所有关键路径均有 info/warn/error 日志,优先查看日志文件与控制台输出。
- 数据库:启动阶段同步表失败会记录警告并继续运行,检查数据库连接与权限。
- S3:凭证缺失或 IAM 角色不可用会导致上传失败,检查 AWS_REGION、AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY。
- Redis:连接超时或认证失败会触发错误事件,检查主机、端口、密码与网络连通性。
- JWT:令牌过期或签名不匹配导致 401,检查密钥与 TTL。
- Meilisearch:404 与状态码特判,确认索引存在与 API Key 正确。
章节来源
- [backend/src/config/logger.js:1-29](file://backend/src/config/logger.js#L1-L29)
- [backend/src/app.js:42-57](file://backend/src/app.js#L42-L57)
- [backend/src/services/measurementStorage.js:76-107](file://backend/src/services/measurementStorage.js#L76-L107)
- [backend/src/config/redis.js:24-26](file://backend/src/config/redis.js#L24-L26)
- [backend/src/utils/jwt.js:21](file://backend/src/utils/jwt.js#L21)
- [backend/src/routes/models.js:89-128](file://backend/src/routes/models.js#L89-L128)
## 结论
本系统通过清晰的配置模块、统一的日志与鉴权、完善的外部系统集成与资源管理,实现了稳定高效的后端服务能力。建议后续在异步任务与跨服务事件方面引入消息队列与可观测性体系,持续提升系统的弹性与可维护性。
## 附录
- 健康检查:根路径与 /health 均无需登录,可用于容器探针与负载均衡健康检查。
- 文档:/docs 与 /redoc 可用于 API 文档浏览。
章节来源
- [backend/src/app.js:22-34](file://backend/src/app.js#L22-L34)