Files
app-api/.qoder/repowiki/zh/content/核心模块/业务处理器.md
T
2026-05-27 18:07:55 +08:00

457 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 业务处理器
<cite>
**本文引用的文件**
- [internal/handler/brand.go](file://internal/handler/brand.go)
- [internal/handler/model.go](file://internal/handler/model.go)
- [internal/handler/model_list.go](file://internal/handler/model_list.go)
- [internal/handler/device.go](file://internal/handler/device.go)
- [internal/handler/health.go](file://internal/handler/health.go)
- [internal/repository/brand.go](file://internal/repository/brand.go)
- [internal/repository/model.go](file://internal/repository/model.go)
- [internal/response/response.go](file://internal/response/response.go)
- [pkg/encode/base64.go](file://pkg/encode/base64.go)
- [internal/search/meilisearch.go](file://internal/search/meilisearch.go)
- [internal/router/router.go](file://internal/router/router.go)
- [cmd/server/main.go](file://cmd/server/main.go)
- [internal/config/config.go](file://internal/config/config.go)
- [internal/middleware/logger.go](file://internal/middleware/logger.go)
- [internal/middleware/cors.go](file://internal/middleware/cors.go)
- [internal/middleware/request_id.go](file://internal/middleware/request_id.go)
- [internal/model/brand.go](file://internal/model/brand.go)
- [internal/model/model.go](file://internal/model/model.go)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考虑](#性能考虑)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件面向 Luxsin 应用 API 的业务处理器模块,系统性梳理各处理器的职责、接口设计与实现细节,覆盖 BrandHandler、ModelHandler、ModelListHandler、DeviceHandler 与 HealthHandler。文档同时阐述依赖注入模式、错误处理机制、响应格式化策略,以及与 Gin 框架的集成方式;并通过流程图与类图展示处理器间的协作关系与数据流转过程,帮助初学者快速上手,同时为高级开发者提供深入的技术参考。
## 项目结构
业务处理器位于 internal/handler 目录,围绕“控制器-仓储-搜索-缓存-响应”的分层组织,配合中间件与路由装配,形成清晰的控制流与依赖注入入口。
```mermaid
graph TB
subgraph "应用入口"
MAIN["cmd/server/main.go<br/>启动与配置加载"]
end
subgraph "路由与中间件"
ROUTER["internal/router/router.go<br/>路由注册与中间件装配"]
CORS["internal/middleware/cors.go"]
LOGMW["internal/middleware/logger.go"]
REQID["internal/middleware/request_id.go"]
end
subgraph "业务处理器"
HEALTH["internal/handler/health.go"]
BRAND["internal/handler/brand.go"]
MODEL["internal/handler/model.go"]
MODELLIST["internal/handler/model_list.go"]
DEVICE["internal/handler/device.go"]
end
subgraph "基础设施"
RESP["internal/response/response.go<br/>统一响应体"]
ENCODE["pkg/encode/base64.go<br/>自定义Base64编码"]
SEARCH["internal/search/meilisearch.go<br/>Meilisearch客户端"]
end
MAIN --> ROUTER
ROUTER --> CORS
ROUTER --> LOGMW
ROUTER --> REQID
ROUTER --> HEALTH
ROUTER --> BRAND
ROUTER --> MODEL
ROUTER --> MODELLIST
ROUTER --> DEVICE
BRAND --> RESP
MODEL --> RESP
MODELLIST --> RESP
DEVICE --> RESP
MODELLIST --> SEARCH
BRAND --> ENCODE
MODEL --> ENCODE
MODELLIST --> ENCODE
```
图表来源
- [cmd/server/main.go:22-96](file://cmd/server/main.go#L22-L96)
- [internal/router/router.go:14-42](file://internal/router/router.go#L14-L42)
- [internal/handler/health.go:8-19](file://internal/handler/health.go#L8-L19)
- [internal/handler/brand.go:14-50](file://internal/handler/brand.go#L14-L50)
- [internal/handler/model.go:14-51](file://internal/handler/model.go#L14-L51)
- [internal/handler/model_list.go:14-57](file://internal/handler/model_list.go#L14-L57)
- [internal/handler/device.go:14-85](file://internal/handler/device.go#L14-L85)
- [internal/response/response.go:9-37](file://internal/response/response.go#L9-L37)
- [pkg/encode/base64.go:8-52](file://pkg/encode/base64.go#L8-L52)
- [internal/search/meilisearch.go:13-46](file://internal/search/meilisearch.go#L13-L46)
章节来源
- [internal/router/router.go:14-42](file://internal/router/router.go#L14-L42)
- [cmd/server/main.go:22-96](file://cmd/server/main.go#L22-L96)
## 核心组件
- 健康检查处理器:提供轻量级健康状态返回,便于外部探活与编排。
- 品牌查询处理器:按品牌名模糊查询品牌列表,支持可选的自定义 Base64 响应。
- 型号查询处理器:按品牌或型号关键字查询型号列表,支持可选的自定义 Base64 响应。
- 型号检索处理器:基于 Meilisearch 执行全文检索,支持可选的自定义 Base64 响应。
- 设备上报处理器:接收设备信息(MAC、型号、版本、来源 IP),写入 Redis Hash。
章节来源
- [internal/handler/health.go:8-19](file://internal/handler/health.go#L8-L19)
- [internal/handler/brand.go:14-50](file://internal/handler/brand.go#L14-L50)
- [internal/handler/model.go:14-51](file://internal/handler/model.go#L14-L51)
- [internal/handler/model_list.go:14-57](file://internal/handler/model_list.go#L14-L57)
- [internal/handler/device.go:14-85](file://internal/handler/device.go#L14-L85)
## 架构总览
下图展示从请求进入至响应返回的关键路径,以及处理器与仓储、搜索、缓存、日志等组件的交互。
```mermaid
sequenceDiagram
participant C as "客户端"
participant R as "Gin 路由"
participant H as "业务处理器"
participant REPO as "仓储层"
participant S as "Meilisearch"
participant RC as "Redis"
participant L as "Zap 日志"
C->>R : "HTTP 请求"
R->>H : "匹配到处理器并调用"
alt "品牌/型号查询"
H->>REPO : "List(ctx, filters)"
REPO-->>H : "结果集"
else "型号检索"
H->>S : "SearchWithContext(key, opts)"
S-->>H : "命中结果"
else "设备上报"
H->>RC : "HSet(mac, json)"
RC-->>H : "OK 或错误"
end
H->>L : "记录日志/错误"
H-->>C : "JSON 或自定义Base64响应"
```
图表来源
- [internal/router/router.go:27-38](file://internal/router/router.go#L27-L38)
- [internal/handler/brand.go:26-49](file://internal/handler/brand.go#L26-L49)
- [internal/handler/model.go:26-50](file://internal/handler/model.go#L26-L50)
- [internal/handler/model_list.go:26-56](file://internal/handler/model_list.go#L26-L56)
- [internal/handler/device.go:26-84](file://internal/handler/device.go#L26-L84)
- [internal/repository/brand.go:20-50](file://internal/repository/brand.go#L20-L50)
- [internal/repository/model.go:20-61](file://internal/repository/model.go#L20-L61)
- [internal/search/meilisearch.go:22-45](file://internal/search/meilisearch.go#L22-L45)
## 详细组件分析
### 健康检查处理器(HealthHandler
- 职责:对外暴露健康检查端点,返回统一响应体中的状态字段。
- 接口设计:无状态对象,构造函数仅初始化空实例。
- 实现要点:
- 使用统一响应体封装返回值。
- 适合被反向代理或编排系统定期探测。
- 典型调用路径:/api/v1/health
章节来源
- [internal/handler/health.go:8-19](file://internal/handler/health.go#L8-L19)
- [internal/response/response.go:9-37](file://internal/response/response.go#L9-L37)
- [internal/router/router.go:29](file://internal/router/router.go#L29)
### 品牌处理器(BrandHandler
- 职责:根据品牌名称模糊查询品牌列表。
- 输入参数:
- 查询字符串:brandName(可选)
- 查询字符串:base64Resp(可选,默认开启)
- 处理流程:
- 读取查询参数并解析 base64Resp。
- 调用仓储层执行数据库查询。
- 若开启 base64Resp,则对结果进行 JSON 编码后返回字符串;否则直接返回 JSON。
- 错误处理:
- 仓储查询失败时记录错误并返回统一内部错误。
- 编码失败时同样返回统一内部错误。
- 数据模型:Brand
```mermaid
classDiagram
class BrandHandler {
-repo : "BrandRepository"
-log : "zap.Logger"
+GetBrand(c)
}
class BrandRepository {
-db : "sql.DB"
+List(ctx, brandName) : "[]Brand,error"
}
class Brand {
+int id
+string name
}
BrandHandler --> BrandRepository : "依赖"
BrandRepository --> Brand : "返回"
```
图表来源
- [internal/handler/brand.go:14-50](file://internal/handler/brand.go#L14-L50)
- [internal/repository/brand.go:12-50](file://internal/repository/brand.go#L12-L50)
- [internal/model/brand.go:3-7](file://internal/model/brand.go#L3-L7)
章节来源
- [internal/handler/brand.go:14-50](file://internal/handler/brand.go#L14-L50)
- [internal/repository/brand.go:20-50](file://internal/repository/brand.go#L20-L50)
- [internal/model/brand.go:3-7](file://internal/model/brand.go#L3-L7)
### 型号处理器(ModelHandler
- 职责:根据品牌或型号关键字查询型号列表。
- 输入参数:
- 查询字符串:brandName(可选)
- 查询字符串:modelName(可选)
- 查询字符串:base64Resp(可选,默认开启)
- 处理流程:
- 读取查询参数并解析 base64Resp。
- 调用仓储层执行数据库查询。
- 结果处理与品牌处理器一致。
- 错误处理:
- 仓储查询失败时记录错误并返回统一内部错误。
- 编码失败时同样返回统一内部错误。
- 数据模型:Model
```mermaid
classDiagram
class ModelHandler {
-repo : "ModelRepository"
-log : "zap.Logger"
+GetModel(c)
}
class ModelRepository {
-db : "sql.DB"
+List(ctx, brandName, modelName) : "[]Model,error"
}
class Model {
+int id
+string brandName
+string name
+*string form
+*string rig
+*string source
+*string eqKey
+time createAt
}
ModelHandler --> ModelRepository : "依赖"
ModelRepository --> Model : "返回"
```
图表来源
- [internal/handler/model.go:14-51](file://internal/handler/model.go#L14-L51)
- [internal/repository/model.go:12-61](file://internal/repository/model.go#L12-L61)
- [internal/model/model.go:5-15](file://internal/model/model.go#L5-L15)
章节来源
- [internal/handler/model.go:14-51](file://internal/handler/model.go#L14-L51)
- [internal/repository/model.go:20-61](file://internal/repository/model.go#L20-L61)
- [internal/model/model.go:5-15](file://internal/model/model.go#L5-L15)
### 型号检索处理器(ModelListHandler
- 职责:基于 Meilisearch 执行全文检索,返回匹配的型号元数据。
- 输入参数:
- 查询字符串:key(必需)
- 查询字符串:count(可选,默认 100)
- 查询字符串:base64Resp(可选,默认开启)
- 处理流程:
- 读取查询参数并解析 base64Resp。
- 限制 count 的最大值以避免过大的返回量。
- 调用搜索客户端执行检索。
- 结果处理与前两个处理器一致。
- 错误处理:
- 检索失败时记录错误并返回统一内部错误。
- 编码失败时同样返回统一内部错误。
- 数据模型:map[string]any(由搜索结果解码而来)
```mermaid
sequenceDiagram
participant C as "客户端"
participant ML as "ModelListHandler"
participant S as "Meilisearch 客户端"
participant E as "自定义Base64"
participant R as "统一响应"
C->>ML : "GET /audio/modelList?key=...&count=..."
ML->>ML : "解析参数与count限制"
ML->>S : "SearchWithContext(key, limit, attributes)"
S-->>ML : "hits"
ML->>E : "可选:EncodeJSON(hits)"
ML-->>C : "JSON 或 Base64(JSON)"
```
图表来源
- [internal/handler/model_list.go:26-56](file://internal/handler/model_list.go#L26-L56)
- [internal/search/meilisearch.go:22-45](file://internal/search/meilisearch.go#L22-L45)
- [pkg/encode/base64.go:35-51](file://pkg/encode/base64.go#L35-L51)
- [internal/response/response.go:15-36](file://internal/response/response.go#L15-L36)
章节来源
- [internal/handler/model_list.go:14-57](file://internal/handler/model_list.go#L14-L57)
- [internal/search/meilisearch.go:22-45](file://internal/search/meilisearch.go#L22-L45)
- [pkg/encode/base64.go:35-51](file://pkg/encode/base64.go#L35-L51)
### 设备上报处理器(DeviceHandler
- 职责:接收设备上报信息(MAC、型号、版本、来源 IP),写入 Redis Hash。
- 输入参数:
- 查询字符串:mac(必填)
- 查询字符串:model(必填)
- 查询字符串:ver(可选)
- 处理流程:
- 校验必填参数,若缺失则返回统一错误响应。
- 组装设备信息结构体(含活跃日期、来源 IP、版本)。
- 将结构体序列化为 JSON 并写入 Redis Hash。
- 返回统一成功响应。
- 错误处理:
- 参数校验失败返回统一错误。
- JSON 序列化失败返回统一错误。
- Redis 写入失败返回统一错误。
- 并发与安全:
- Redis HSet 是原子操作,适合高并发场景。
- 建议对 MAC 去除空白字符,避免重复键。
```mermaid
flowchart TD
Start(["进入 ReportDevInfo"]) --> ReadParams["读取参数 mac/model/ver/X-Forwarded-For"]
ReadParams --> Validate{"参数校验通过?"}
Validate -- 否 --> RespFail["返回统一错误响应"]
Validate -- 是 --> BuildInfo["组装设备信息结构体"]
BuildInfo --> Marshal{"JSON序列化成功?"}
Marshal -- 否 --> RespFail
Marshal -- 是 --> HSet["Redis HSet(mac, json)"]
HSet --> SetOK{"写入成功?"}
SetOK -- 否 --> RespFail
SetOK -- 是 --> RespOK["返回统一成功响应"]
RespFail --> End(["结束"])
RespOK --> End
```
图表来源
- [internal/handler/device.go:26-84](file://internal/handler/device.go#L26-L84)
章节来源
- [internal/handler/device.go:14-85](file://internal/handler/device.go#L14-L85)
## 依赖分析
- 依赖注入模式:
- 控制器通过构造函数注入仓储、搜索客户端、Redis 客户端与日志器。
- 路由在应用启动时集中装配,保证依赖一次性构建与共享。
- 组件耦合:
- 处理器与仓储之间为单向依赖,职责清晰。
- 搜索与缓存作为外部服务,通过客户端封装接入。
- 可能的循环依赖:
- 当前结构未见循环导入,符合 Go 包管理最佳实践。
```mermaid
graph LR
MAIN["main.go"] --> ROUTER["router.go"]
ROUTER --> HEALTH["health.go"]
ROUTER --> BRAND["brand.go"]
ROUTER --> MODEL["model.go"]
ROUTER --> MODELLIST["model_list.go"]
ROUTER --> DEVICE["device.go"]
BRAND --> BREPO["repository/brand.go"]
MODEL --> MREPO["repository/model.go"]
MODELLIST --> SEARCH["search/meilisearch.go"]
DEVICE --> REDIS["Redis 客户端"]
BRAND --> ENCODE["pkg/encode/base64.go"]
MODEL --> ENCODE
MODELLIST --> ENCODE
ALL["各处理器"] --> RESP["internal/response/response.go"]
ALL --> LOG["zap.Logger"]
```
图表来源
- [cmd/server/main.go:64](file://cmd/server/main.go#L64)
- [internal/router/router.go:21-25](file://internal/router/router.go#L21-L25)
- [internal/handler/brand.go:19-24](file://internal/handler/brand.go#L19-L24)
- [internal/handler/model.go:19-24](file://internal/handler/model.go#L19-L24)
- [internal/handler/model_list.go:19-24](file://internal/handler/model_list.go#L19-L24)
- [internal/handler/device.go:19-24](file://internal/handler/device.go#L19-L24)
- [internal/repository/brand.go:16](file://internal/repository/brand.go#L16)
- [internal/repository/model.go:16](file://internal/repository/model.go#L16)
- [internal/search/meilisearch.go:17](file://internal/search/meilisearch.go#L17)
- [pkg/encode/base64.go:8](file://pkg/encode/base64.go#L8)
- [internal/response/response.go:9](file://internal/response/response.go#L9)
章节来源
- [internal/router/router.go:14-42](file://internal/router/router.go#L14-L42)
- [cmd/server/main.go:22-96](file://cmd/server/main.go#L22-L96)
## 性能考虑
- 响应体积优化
- 对于大结果集,优先启用自定义 Base64 响应,减少传输体积与字符转义开销。
- 检索处理器对 count 进行上限控制,避免超大数据量返回。
- 数据库查询
- 品牌与型号查询均使用 ORDER BY 与 LIKE,建议在数据库侧建立合适索引以提升模糊查询性能。
- 搜索与缓存
- Meilisearch 适合全文检索,建议合理设置属性检索范围与分页大小。
- Redis 写入为单键 HSet,具备良好吞吐能力;建议评估内存占用与持久化策略。
- 中间件与日志
- 开启 Recovery、CORS、Logger、RequestID 中间件,有助于可观测性与稳定性;注意日志级别与输出频率对性能的影响。
- 并发安全
- Redis HSet 为线程安全操作;处理器方法本身无共享可变状态,天然并发安全。
- 最佳实践
- 在生产环境启用 Release 模式,降低框架开销。
- 对外部依赖(数据库、搜索、缓存)增加超时与重试策略,提升鲁棒性。
## 故障排查指南
- 健康检查失败
- 确认路由已正确注册到 /api/v1/health。
- 查看统一响应体是否返回状态字段。
- 品牌/型号查询异常
- 检查数据库连接与 SQL 查询逻辑。
- 关注日志中“query brand”、“query model”的错误堆栈。
- 型号检索异常
- 检查 Meilisearch 配置与索引可用性。
- 关注“meilisearch search”与“decode meilisearch hit”的错误。
- 设备上报异常
- 校验必填参数 mac 与 model 是否传入。
- 关注 JSON 序列化与 Redis HSet 的错误日志。
- 统一响应与错误码
- 使用 internal/response/response.go 提供的 OK/Fail/BadRequest/InternalError 方法,确保错误码与消息格式一致。
- 日志与追踪
- 通过 RequestID 中间件串联一次请求的全链路日志,结合 Logger 中间件定位问题。
章节来源
- [internal/handler/health.go:14-18](file://internal/handler/health.go#L14-L18)
- [internal/handler/brand.go:31-35](file://internal/handler/brand.go#L31-L35)
- [internal/handler/model.go:32-36](file://internal/handler/model.go#L32-L36)
- [internal/handler/model_list.go:38-42](file://internal/handler/model_list.go#L38-L42)
- [internal/handler/device.go:61-78](file://internal/handler/device.go#L61-L78)
- [internal/response/response.go:15-36](file://internal/response/response.go#L15-L36)
- [internal/middleware/logger.go:10-45](file://internal/middleware/logger.go#L10-L45)
- [internal/middleware/request_id.go:20-31](file://internal/middleware/request_id.go#L20-L31)
## 结论
本处理器模块遵循清晰的分层与依赖注入原则,通过统一响应体与自定义 Base64 编码实现灵活的输出策略,结合 Gin 中间件与外部服务(数据库、Meilisearch、Redis)形成稳定高效的业务处理链路。建议在生产环境中进一步完善超时与重试、索引优化与缓存策略,持续提升性能与可靠性。
## 附录
- 路由与处理器映射
- /api/v1/health -> HealthHandler.Check
- /audio/getBrand -> BrandHandler.GetBrand
- /audio/getModel -> ModelHandler.GetModel
- /audio/modelList -> ModelListHandler.ModelList
- /audio/reportDevInfo -> DeviceHandler.ReportDevInfo
- 常用调用示例(路径引用)
- 品牌查询:[internal/handler/brand.go:26](file://internal/handler/brand.go#L26)
- 型号查询:[internal/handler/model.go:26](file://internal/handler/model.go#L26)
- 型号检索:[internal/handler/model_list.go:26](file://internal/handler/model_list.go#L26)
- 设备上报:[internal/handler/device.go:26](file://internal/handler/device.go#L26)
- 健康检查:[internal/handler/health.go:14](file://internal/handler/health.go#L14)
- 配置与启动
- 配置加载与环境变量:[internal/config/config.go:18-64](file://internal/config/config.go#L18-L64)
- 服务器启动与优雅关闭:[cmd/server/main.go:22-96](file://cmd/server/main.go#L22-L96)
- 中间件
- CORS[internal/middleware/cors.go:7-21](file://internal/middleware/cors.go#L7-L21)
- Logger[internal/middleware/logger.go:10-45](file://internal/middleware/logger.go#L10-L45)
- RequestID[internal/middleware/request_id.go:20-31](file://internal/middleware/request_id.go#L20-L31)