484 lines
18 KiB
Markdown
484 lines
18 KiB
Markdown
# 系统架构
|
||
|
||
<cite>
|
||
**本文引用的文件**
|
||
- [cmd/server/main.go](file://cmd/server/main.go)
|
||
- [internal/config/config.go](file://internal/config/config.go)
|
||
- [internal/config/database.go](file://internal/config/database.go)
|
||
- [internal/config/meilisearch.go](file://internal/config/meilisearch.go)
|
||
- [internal/config/redis.go](file://internal/config/redis.go)
|
||
- [internal/router/router.go](file://internal/router/router.go)
|
||
- [internal/handler/health.go](file://internal/handler/health.go)
|
||
- [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/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/database/mysql.go](file://internal/database/mysql.go)
|
||
- [internal/cache/redis.go](file://internal/cache/redis.go)
|
||
- [internal/search/meilisearch.go](file://internal/search/meilisearch.go)
|
||
- [internal/response/response.go](file://internal/response/response.go)
|
||
- [pkg/logger/logger.go](file://pkg/logger/logger.go)
|
||
- [go.mod](file://go.mod)
|
||
- [README.md](file://README.md)
|
||
- [Makefile](file://Makefile)
|
||
</cite>
|
||
|
||
## 目录
|
||
1. [引言](#引言)
|
||
2. [项目结构](#项目结构)
|
||
3. [核心组件](#核心组件)
|
||
4. [架构总览](#架构总览)
|
||
5. [详细组件分析](#详细组件分析)
|
||
6. [依赖关系分析](#依赖关系分析)
|
||
7. [性能考量](#性能考量)
|
||
8. [故障排查指南](#故障排查指南)
|
||
9. [结论](#结论)
|
||
10. [附录](#附录)
|
||
|
||
## 引言
|
||
本文件为 Luxsin 应用 API 项目的系统架构文档,聚焦于高层设计、架构模式与系统边界。项目采用分层架构(表现层、业务层、数据访问层、基础设施层),结合依赖注入、中间件与工厂等模式,形成清晰的职责划分与可维护性。系统围绕 Gin HTTP 框架构建,集成 MySQL、Redis 与 Meilisearch,提供健康检查、品牌与型号查询、设备信息上报以及模型检索等能力。
|
||
|
||
## 项目结构
|
||
项目采用按领域与层次混合的组织方式:
|
||
- cmd/server:程序入口,负责配置加载、资源初始化、HTTP 服务启动与优雅关闭
|
||
- internal:核心业务域
|
||
- config:集中式配置加载与校验
|
||
- router:路由注册与中间件装配
|
||
- handler:HTTP 处理器,面向具体接口
|
||
- middleware:横切关注点(日志、CORS、Request ID)
|
||
- database:数据库连接工厂与生命周期管理
|
||
- cache:Redis 客户端工厂
|
||
- search:Meilisearch 客户端与搜索逻辑
|
||
- response:统一响应体封装
|
||
- model/repository:模型与仓储抽象(当前未在路由中使用)
|
||
- pkg:可复用工具模块(日志封装)
|
||
- sql:数据库初始化脚本
|
||
- 根目录:构建与依赖声明
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "应用进程"
|
||
MAIN["cmd/server/main.go<br/>程序入口"]
|
||
ROUTER["internal/router/router.go<br/>路由与中间件"]
|
||
HANDLERS["internal/handler/*<br/>HTTP处理器"]
|
||
RESP["internal/response/response.go<br/>统一响应"]
|
||
end
|
||
subgraph "配置与基础设施"
|
||
CFG["internal/config/*.go<br/>配置加载/校验"]
|
||
LOGPKG["pkg/logger/logger.go<br/>日志封装"]
|
||
MYSQL["internal/database/mysql.go<br/>MySQL工厂"]
|
||
REDIS["internal/cache/redis.go<br/>Redis工厂"]
|
||
MS["internal/search/meilisearch.go<br/>Meilisearch客户端"]
|
||
end
|
||
MAIN --> CFG
|
||
MAIN --> MYSQL
|
||
MAIN --> REDIS
|
||
MAIN --> MS
|
||
MAIN --> ROUTER
|
||
ROUTER --> HANDLERS
|
||
HANDLERS --> RESP
|
||
MAIN --> LOGPKG
|
||
```
|
||
|
||
图表来源
|
||
- [cmd/server/main.go:1-96](file://cmd/server/main.go#L1-L96)
|
||
- [internal/router/router.go:1-42](file://internal/router/router.go#L1-L42)
|
||
- [internal/config/config.go:1-64](file://internal/config/config.go#L1-L64)
|
||
- [pkg/logger/logger.go:1-20](file://pkg/logger/logger.go#L1-L20)
|
||
- [internal/database/mysql.go:1-47](file://internal/database/mysql.go#L1-L47)
|
||
- [internal/cache/redis.go:1-17](file://internal/cache/redis.go#L1-L17)
|
||
- [internal/search/meilisearch.go:1-46](file://internal/search/meilisearch.go#L1-L46)
|
||
- [internal/response/response.go:1-37](file://internal/response/response.go#L1-L37)
|
||
|
||
章节来源
|
||
- [README.md:5-17](file://README.md#L5-L17)
|
||
- [go.mod:1-47](file://go.mod#L1-L47)
|
||
|
||
## 核心组件
|
||
- 配置中心:集中加载运行环境、主机、端口、数据库、搜索引擎与缓存参数,并进行必要校验
|
||
- 日志封装:按环境输出不同编码风格的日志,便于生产与开发调试
|
||
- 数据库工厂:构造 MySQL 连接池,设置连接上限、空闲数与生命周期,并进行超时探测
|
||
- 缓存工厂:构造 Redis 客户端实例
|
||
- 搜索引擎客户端:封装 Meilisearch 搜索请求,限定返回字段
|
||
- 路由与中间件:装配 Recovery、Request ID、Logger、CORS,并注册各业务路由
|
||
- HTTP 处理器:面向具体接口(健康检查、品牌、型号、模型列表、设备信息上报)
|
||
- 统一响应:标准化返回结构,简化错误码与消息传递
|
||
|
||
章节来源
|
||
- [internal/config/config.go:18-56](file://internal/config/config.go#L18-L56)
|
||
- [pkg/logger/logger.go:8-19](file://pkg/logger/logger.go#L8-L19)
|
||
- [internal/database/mysql.go:14-46](file://internal/database/mysql.go#L14-L46)
|
||
- [internal/cache/redis.go:10-16](file://internal/cache/redis.go#L10-L16)
|
||
- [internal/search/meilisearch.go:17-45](file://internal/search/meilisearch.go#L17-L45)
|
||
- [internal/router/router.go:14-41](file://internal/router/router.go#L14-L41)
|
||
- [internal/handler/health.go:14-18](file://internal/handler/health.go#L14-L18)
|
||
- [internal/response/response.go:9-36](file://internal/response/response.go#L9-L36)
|
||
|
||
## 架构总览
|
||
系统采用“入口—配置—基础设施—路由—处理器”的分层结构,入口负责组装依赖并通过工厂创建基础设施客户端,路由层装配中间件并注册业务接口,处理器层完成业务逻辑与数据访问。
|
||
|
||
```mermaid
|
||
graph TB
|
||
CLIENT["客户端/调用方"]
|
||
ENTRY["cmd/server/main.go<br/>启动与依赖注入"]
|
||
CONF["internal/config/*.go<br/>配置加载/校验"]
|
||
LOG["pkg/logger/logger.go<br/>日志"]
|
||
DBF["internal/database/mysql.go<br/>MySQL工厂"]
|
||
REDF["internal/cache/redis.go<br/>Redis工厂"]
|
||
MSF["internal/search/meilisearch.go<br/>Meilisearch工厂"]
|
||
RT["internal/router/router.go<br/>路由与中间件"]
|
||
H1["internal/handler/health.go"]
|
||
H2["internal/handler/brand.go"]
|
||
H3["internal/handler/model.go"]
|
||
H4["internal/handler/model_list.go"]
|
||
H5["internal/handler/device.go"]
|
||
CLIENT --> ENTRY
|
||
ENTRY --> CONF
|
||
ENTRY --> DBF
|
||
ENTRY --> REDF
|
||
ENTRY --> MSF
|
||
ENTRY --> LOG
|
||
ENTRY --> RT
|
||
RT --> H1
|
||
RT --> H2
|
||
RT --> H3
|
||
RT --> H4
|
||
RT --> H5
|
||
```
|
||
|
||
图表来源
|
||
- [cmd/server/main.go:22-64](file://cmd/server/main.go#L22-L64)
|
||
- [internal/router/router.go:14-41](file://internal/router/router.go#L14-L41)
|
||
- [internal/handler/health.go:10-18](file://internal/handler/health.go#L10-L18)
|
||
- [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)
|
||
|
||
## 详细组件分析
|
||
|
||
### 入口与控制流(main)
|
||
- 加载配置并根据环境设置 Gin 运行模式
|
||
- 初始化日志、数据库、搜索引擎与缓存客户端
|
||
- 创建 Gin 引擎并启动 HTTP 服务器
|
||
- 支持优雅关闭,处理系统信号
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant OS as "操作系统"
|
||
participant Main as "main.go"
|
||
participant Cfg as "config.Load()"
|
||
participant Log as "logger.New()"
|
||
participant DB as "database.Open()"
|
||
participant MS as "search.NewClient()"
|
||
participant RC as "cache.NewClient()"
|
||
participant RT as "router.New()"
|
||
OS->>Main : 启动进程
|
||
Main->>Cfg : 加载配置
|
||
Main->>Log : 初始化日志
|
||
Main->>DB : 打开数据库连接
|
||
Main->>MS : 初始化搜索引擎
|
||
Main->>RC : 初始化缓存
|
||
Main->>RT : 创建路由引擎
|
||
Main->>OS : 启动HTTP服务
|
||
```
|
||
|
||
图表来源
|
||
- [cmd/server/main.go:22-96](file://cmd/server/main.go#L22-L96)
|
||
|
||
章节来源
|
||
- [cmd/server/main.go:22-96](file://cmd/server/main.go#L22-L96)
|
||
|
||
### 配置加载与校验
|
||
- 从环境变量读取运行参数,支持默认值
|
||
- 分别加载数据库、搜索引擎与缓存配置并执行校验
|
||
- 提供 Addr() 计算监听地址
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
Start(["启动"]) --> LoadEnv["读取环境变量"]
|
||
LoadEnv --> LoadDB["加载数据库配置并校验"]
|
||
LoadDB --> LoadMS["加载搜索引擎配置并校验"]
|
||
LoadMS --> LoadRD["加载Redis配置并校验"]
|
||
LoadRD --> BuildCfg["构建Config对象"]
|
||
BuildCfg --> End(["完成"])
|
||
```
|
||
|
||
图表来源
|
||
- [internal/config/config.go:18-56](file://internal/config/config.go#L18-L56)
|
||
|
||
章节来源
|
||
- [internal/config/config.go:18-56](file://internal/config/config.go#L18-L56)
|
||
|
||
### 路由与中间件
|
||
- 使用 Gin.New() 创建引擎,启用 Recovery
|
||
- 注册中间件:Request ID、Logger、CORS
|
||
- 注册业务路由分组与接口
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant RT as "router.New()"
|
||
participant MW1 as "RequestID"
|
||
participant MW2 as "Logger"
|
||
participant MW3 as "CORS"
|
||
participant H as "handlers"
|
||
RT->>MW1 : Use(RequestID)
|
||
RT->>MW2 : Use(Logger)
|
||
RT->>MW3 : Use(CORS)
|
||
RT->>H : 注册健康检查/品牌/型号/模型列表/设备上报
|
||
```
|
||
|
||
图表来源
|
||
- [internal/router/router.go:14-41](file://internal/router/router.go#L14-L41)
|
||
- [internal/middleware/request_id.go:20-30](file://internal/middleware/request_id.go#L20-L30)
|
||
- [internal/middleware/logger.go:10-45](file://internal/middleware/logger.go#L10-L45)
|
||
- [internal/middleware/cors.go:7-20](file://internal/middleware/cors.go#L7-L20)
|
||
|
||
章节来源
|
||
- [internal/router/router.go:14-41](file://internal/router/router.go#L14-L41)
|
||
- [internal/middleware/request_id.go:10-31](file://internal/middleware/request_id.go#L10-L31)
|
||
- [internal/middleware/logger.go:10-46](file://internal/middleware/logger.go#L10-L46)
|
||
- [internal/middleware/cors.go:7-21](file://internal/middleware/cors.go#L7-L21)
|
||
|
||
### 数据访问层(数据库/缓存/搜索)
|
||
- 数据库:通过工厂函数创建 sql.DB,设置连接池参数并 Ping 校验
|
||
- 缓存:通过工厂函数创建 Redis 客户端
|
||
- 搜索:通过工厂函数创建 Meilisearch 客户端,提供模型列表检索
|
||
|
||
```mermaid
|
||
classDiagram
|
||
class DBFactory {
|
||
+Open(cfg) *sql.DB
|
||
}
|
||
class RedisFactory {
|
||
+NewClient(cfg) *redis.Client
|
||
}
|
||
class SearchClient {
|
||
+ModelList(ctx, key, count) []map[string]any
|
||
}
|
||
DBFactory --> "*sql.DB" : "创建"
|
||
RedisFactory --> "*redis.Client" : "创建"
|
||
SearchClient --> "meilisearch.IndexManager" : "封装"
|
||
```
|
||
|
||
图表来源
|
||
- [internal/database/mysql.go:14-46](file://internal/database/mysql.go#L14-L46)
|
||
- [internal/cache/redis.go:10-16](file://internal/cache/redis.go#L10-L16)
|
||
- [internal/search/meilisearch.go:17-45](file://internal/search/meilisearch.go#L17-L45)
|
||
|
||
章节来源
|
||
- [internal/database/mysql.go:14-46](file://internal/database/mysql.go#L14-L46)
|
||
- [internal/cache/redis.go:10-16](file://internal/cache/redis.go#L10-L16)
|
||
- [internal/search/meilisearch.go:17-45](file://internal/search/meilisearch.go#L17-L45)
|
||
|
||
### 处理器与统一响应
|
||
- 处理器:健康检查、品牌、型号、模型列表、设备信息上报
|
||
- 统一响应:OK/Fail/BadRequest/InternalError 等方法,保证返回结构一致
|
||
|
||
```mermaid
|
||
classDiagram
|
||
class Handler {
|
||
<<interface>>
|
||
+Check(c)
|
||
}
|
||
class BrandHandler {
|
||
+GetBrand(c)
|
||
}
|
||
class ModelHandler {
|
||
+GetModel(c)
|
||
}
|
||
class ModelListHandler {
|
||
+ModelList(c)
|
||
}
|
||
class DeviceHandler {
|
||
+ReportDevInfo(c)
|
||
}
|
||
class Response {
|
||
+OK(c,data)
|
||
+Fail(c,status,code,msg)
|
||
+BadRequest(c,msg)
|
||
+InternalError(c,msg)
|
||
}
|
||
Handler <|.. BrandHandler
|
||
Handler <|.. ModelHandler
|
||
Handler <|.. ModelListHandler
|
||
Handler <|.. DeviceHandler
|
||
BrandHandler --> Response : "使用"
|
||
ModelHandler --> Response : "使用"
|
||
ModelListHandler --> Response : "使用"
|
||
DeviceHandler --> Response : "使用"
|
||
```
|
||
|
||
图表来源
|
||
- [internal/handler/health.go:8-18](file://internal/handler/health.go#L8-L18)
|
||
- [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/response/response.go:9-36](file://internal/response/response.go#L9-L36)
|
||
|
||
章节来源
|
||
- [internal/handler/health.go:8-18](file://internal/handler/health.go#L8-L18)
|
||
- [internal/response/response.go:9-36](file://internal/response/response.go#L9-L36)
|
||
|
||
### 关键流程示例:健康检查
|
||
- 请求进入 /api/v1/health
|
||
- 经过中间件链路后交由 HealthHandler 处理
|
||
- 使用统一响应返回状态
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant C as "客户端"
|
||
participant G as "Gin引擎"
|
||
participant MW as "中间件链"
|
||
participant H as "HealthHandler"
|
||
participant R as "Response"
|
||
C->>G : GET /api/v1/health
|
||
G->>MW : 执行中间件
|
||
MW-->>G : 继续
|
||
G->>H : Check(c)
|
||
H->>R : OK(c, {status : "up"})
|
||
R-->>C : JSON响应
|
||
```
|
||
|
||
图表来源
|
||
- [internal/router/router.go:27-30](file://internal/router/router.go#L27-L30)
|
||
- [internal/handler/health.go:14-18](file://internal/handler/health.go#L14-L18)
|
||
- [internal/response/response.go:15-21](file://internal/response/response.go#L15-L21)
|
||
|
||
章节来源
|
||
- [internal/router/router.go:27-30](file://internal/router/router.go#L27-L30)
|
||
- [internal/handler/health.go:14-18](file://internal/handler/health.go#L14-L18)
|
||
- [internal/response/response.go:15-21](file://internal/response/response.go#L15-L21)
|
||
|
||
## 依赖关系分析
|
||
- 技术栈与版本
|
||
- Go 1.24.0
|
||
- Gin 1.10.0、MySQL Driver 1.10.0、Meilisearch Go SDK 0.36.2、Redis Go-Redis 9.19.0、Zap 1.27.0
|
||
- 间接依赖:大量通过 go.mod 标注的间接依赖,确保高性能与安全更新
|
||
- 版本兼容性:Go 1.24 与各依赖版本在 go.mod 中明确声明,遵循语义化版本
|
||
|
||
```mermaid
|
||
graph LR
|
||
GO["Go 1.24.0"]
|
||
GIN["Gin 1.10.0"]
|
||
MYSQLDRV["MySQL Driver 1.10.0"]
|
||
MS["Meilisearch SDK 0.36.2"]
|
||
REDIS["Redis Go-Redis 9.19.0"]
|
||
ZAP["Zap 1.27.0"]
|
||
GO --> GIN
|
||
GO --> MYSQLDRV
|
||
GO --> MS
|
||
GO --> REDIS
|
||
GO --> ZAP
|
||
```
|
||
|
||
图表来源
|
||
- [go.mod:3-11](file://go.mod#L3-L11)
|
||
|
||
章节来源
|
||
- [go.mod:3-47](file://go.mod#L3-L47)
|
||
|
||
## 性能考量
|
||
- 连接池与生命周期
|
||
- 数据库连接池:最大并发、空闲连接数与连接最长存活时间已设置,有助于控制资源占用与抖动
|
||
- Redis 客户端:通过工厂创建,建议在处理器中复用以减少连接开销
|
||
- 超时与稳定性
|
||
- HTTP 服务器设置读/写/空闲超时,避免慢请求导致资源泄漏
|
||
- 数据库 Ping 设置超时上下文,防止启动阻塞
|
||
- 日志级别与开销
|
||
- 生产环境使用生产配置,减少编码开销;开发环境彩色编码提升可观测性
|
||
- 搜索性能
|
||
- 搜索限制返回字段与数量,降低网络与解析成本
|
||
|
||
章节来源
|
||
- [internal/database/mysql.go:33-43](file://internal/database/mysql.go#L33-L43)
|
||
- [cmd/server/main.go:66-72](file://cmd/server/main.go#L66-L72)
|
||
- [pkg/logger/logger.go:10-17](file://pkg/logger/logger.go#L10-L17)
|
||
- [internal/search/meilisearch.go:22-29](file://internal/search/meilisearch.go#L22-L29)
|
||
|
||
## 故障排查指南
|
||
- 启动失败
|
||
- 检查配置加载是否成功(环境变量、默认值、校验)
|
||
- 查看数据库连接日志与错误信息
|
||
- 接口异常
|
||
- 通过 Request ID 定位请求链路
|
||
- 根据日志中的状态码、路径、延迟与错误信息定位问题
|
||
- 搜索无结果
|
||
- 确认索引与 API Key 配置正确
|
||
- 检查检索关键字与返回字段映射
|
||
- 缓存不可用
|
||
- 校验 Redis 地址、端口与认证信息
|
||
|
||
章节来源
|
||
- [cmd/server/main.go:32-58](file://cmd/server/main.go#L32-L58)
|
||
- [internal/middleware/logger.go:10-45](file://internal/middleware/logger.go#L10-L45)
|
||
- [internal/middleware/request_id.go:20-30](file://internal/middleware/request_id.go#L20-L30)
|
||
- [internal/search/meilisearch.go:17-20](file://internal/search/meilisearch.go#L17-L20)
|
||
- [internal/cache/redis.go:10-16](file://internal/cache/redis.go#L10-L16)
|
||
|
||
## 结论
|
||
本项目通过清晰的分层架构与工厂/中间件/依赖注入模式,实现了高内聚、低耦合的服务结构。入口负责依赖装配,路由与中间件提供横切能力,处理器与统一响应保障接口一致性。结合数据库连接池、日志与超时策略,系统具备良好的性能与可维护性。后续可在安全、监控与灾备方面进一步增强。
|
||
|
||
## 附录
|
||
|
||
### 系统上下文图
|
||
```mermaid
|
||
graph TB
|
||
U["用户/客户端"]
|
||
S["应用进程"]
|
||
D["MySQL"]
|
||
K["Redis"]
|
||
E["Meilisearch"]
|
||
U --> S
|
||
S --> D
|
||
S --> K
|
||
S --> E
|
||
```
|
||
|
||
图表来源
|
||
- [cmd/server/main.go:38-57](file://cmd/server/main.go#L38-L57)
|
||
- [internal/database/mysql.go:14-46](file://internal/database/mysql.go#L14-L46)
|
||
- [internal/cache/redis.go:10-16](file://internal/cache/redis.go#L10-L16)
|
||
- [internal/search/meilisearch.go:17-20](file://internal/search/meilisearch.go#L17-L20)
|
||
|
||
### 组件分解图
|
||
```mermaid
|
||
graph TB
|
||
MAIN["main.go"]
|
||
CFG["config/*.go"]
|
||
LOG["pkg/logger/logger.go"]
|
||
DB["internal/database/mysql.go"]
|
||
RC["internal/cache/redis.go"]
|
||
MS["internal/search/meilisearch.go"]
|
||
RT["internal/router/router.go"]
|
||
H["internal/handler/*"]
|
||
RESP["internal/response/response.go"]
|
||
MAIN --> CFG
|
||
MAIN --> LOG
|
||
MAIN --> DB
|
||
MAIN --> RC
|
||
MAIN --> MS
|
||
MAIN --> RT
|
||
RT --> H
|
||
H --> RESP
|
||
```
|
||
|
||
图表来源
|
||
- [cmd/server/main.go:22-64](file://cmd/server/main.go#L22-L64)
|
||
- [internal/router/router.go:14-41](file://internal/router/router.go#L14-L41)
|
||
- [internal/response/response.go:9-36](file://internal/response/response.go#L9-L36)
|
||
|
||
### 部署拓扑与基础设施要求
|
||
- 运行环境:Go 1.24+
|
||
- 依赖服务:MySQL、Redis、Meilisearch
|
||
- 监听地址与端口:由配置决定,默认 0.0.0.0:8080
|
||
- 构建与运行:Makefile 提供 run/build/test/tidy 目标
|
||
|
||
章节来源
|
||
- [README.md:21-29](file://README.md#L21-L29)
|
||
- [README.md:75-81](file://README.md#L75-L81)
|
||
- [Makefile:3-14](file://Makefile#L3-L14) |