# 分层架构设计
**本文档引用的文件**
- [main.go](file://cmd/server/main.go)
- [router.go](file://internal/router/router.go)
- [config.go](file://internal/config/config.go)
- [database.go](file://internal/config/database.go)
- [meilisearch_config.go](file://internal/config/meilisearch.go)
- [redis_config.go](file://internal/config/redis.go)
- [mysql.go](file://internal/database/mysql.go)
- [redis.go](file://internal/cache/redis.go)
- [meilisearch.go](file://internal/search/meilisearch.go)
- [health.go](file://internal/handler/health.go)
- [brand.go](file://internal/handler/brand.go)
- [model.go](file://internal/handler/model.go)
- [brand_repository.go](file://internal/repository/brand.go)
- [brand_model.go](file://internal/model/brand.go)
- [logger_middleware.go](file://internal/middleware/logger.go)
## 目录
1. [引言](#引言)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考虑](#性能考虑)
8. [故障排除指南](#故障排除指南)
9. [结论](#结论)
## 引言
本项目采用分层架构设计,围绕表现层(Router/Handler)、业务层(Repository)、数据访问层(Database/Cache/Search)与基础设施层(Middleware/Logger)进行职责分离。通过构造函数注入依赖的方式,实现清晰的依赖关系与可测试性。MVC 的变体实现体现在:表现层负责路由与请求响应;业务层封装领域逻辑与查询;数据访问层抽象数据库、缓存与搜索引擎;基础设施层提供横切关注点如日志、CORS、请求 ID 等。
## 项目结构
项目按功能域分层组织,核心目录如下:
- cmd/server:应用入口,负责初始化配置、连接外部服务、启动 HTTP 服务器
- internal/config:配置加载与校验,支持环境变量覆盖
- internal/router:路由注册与中间件装配
- internal/handler:HTTP 处理器,面向路由端点,调用仓库与工具
- internal/repository:业务仓储,封装数据库查询与映射
- internal/database:数据库连接与池化配置
- internal/cache:Redis 客户端初始化
- internal/search:Meilisearch 客户端初始化与搜索接口
- internal/middleware:Gin 中间件,统一处理日志、CORS、请求 ID
- internal/model:领域模型定义
- internal/response:统一响应封装
- pkg/encode:编码工具(如 Base64)
- pkg/logger:日志初始化
```mermaid
graph TB
subgraph "表现层"
Router["Router
internal/router/router.go"]
Handlers["Handlers
internal/handler/*"]
end
subgraph "业务层"
Repositories["Repositories
internal/repository/*"]
Models["Models
internal/model/*"]
end
subgraph "数据访问层"
DB["MySQL 连接
internal/database/mysql.go"]
Redis["Redis 客户端
internal/cache/redis.go"]
Search["Meilisearch 客户端
internal/search/meilisearch.go"]
end
subgraph "基础设施层"
Middleware["中间件
internal/middleware/*"]
LoggerPkg["日志包
pkg/logger/*"]
Encode["编码工具
pkg/encode/*"]
end
subgraph "入口"
Main["主程序
cmd/server/main.go"]
Config["配置
internal/config/*"]
end
Main --> Config
Main --> DB
Main --> Redis
Main --> Search
Main --> Router
Router --> Middleware
Router --> Handlers
Handlers --> Repositories
Repositories --> DB
Handlers --> Redis
Handlers --> Search
Handlers --> Encode
Handlers --> LoggerPkg
```
**图示来源**
- [main.go:1-96](file://cmd/server/main.go#L1-L96)
- [router.go:1-42](file://internal/router/router.go#L1-L42)
- [mysql.go:1-47](file://internal/database/mysql.go#L1-L47)
- [redis.go:1-17](file://internal/cache/redis.go#L1-L17)
- [meilisearch.go:1-46](file://internal/search/meilisearch.go#L1-L46)
- [config.go:1-64](file://internal/config/config.go#L1-L64)
**章节来源**
- [main.go:1-96](file://cmd/server/main.go#L1-L96)
- [router.go:1-42](file://internal/router/router.go#L1-L42)
- [config.go:1-64](file://internal/config/config.go#L1-L64)
## 核心组件
- 表现层(Router/Handler)
- 路由器负责注册路由组与中间件,将 HTTP 请求映射到处理器
- 处理器接收请求参数,调用仓库或外部服务,返回统一响应
- 业务层(Repository)
- 封装数据库查询逻辑,负责数据读取与映射
- 数据访问层(Database/Cache/Search)
- 提供数据库连接池、Redis 客户端与 Meilisearch 客户端
- 基础设施层(Middleware/Logger)
- 提供日志、CORS、请求 ID 等横切能力
**章节来源**
- [router.go:14-41](file://internal/router/router.go#L14-L41)
- [brand.go:19-24](file://internal/handler/brand.go#L19-L24)
- [brand_repository.go:16-18](file://internal/repository/brand.go#L16-L18)
- [mysql.go:14-46](file://internal/database/mysql.go#L14-L46)
- [redis.go:10-16](file://internal/cache/redis.go#L10-L16)
- [meilisearch.go:17-20](file://internal/search/meilisearch.go#L17-L20)
- [logger_middleware.go:10-45](file://internal/middleware/logger.go#L10-L45)
## 架构总览
下图展示了从入口到各层的完整调用链路与依赖方向:
```mermaid
sequenceDiagram
participant Client as "客户端"
participant Main as "主程序
cmd/server/main.go"
participant Router as "路由器
internal/router/router.go"
participant Handler as "处理器
internal/handler/*"
participant Repo as "仓库
internal/repository/*"
participant DB as "数据库
internal/database/mysql.go"
participant Redis as "Redis
internal/cache/redis.go"
participant Search as "Meilisearch
internal/search/meilisearch.go"
Client->>Main : 启动进程
Main->>Main : 加载配置/初始化日志
Main->>DB : 打开数据库连接
Main->>Redis : 创建客户端
Main->>Search : 创建客户端
Main->>Router : 注册路由与中间件
Client->>Router : 发起 HTTP 请求
Router->>Handler : 调用对应处理器
Handler->>Repo : 执行业务查询
Repo->>DB : 执行 SQL 查询
DB-->>Repo : 返回结果集
Repo-->>Handler : 返回领域对象列表
Handler-->>Client : 统一响应
```
**图示来源**
- [main.go:22-64](file://cmd/server/main.go#L22-L64)
- [router.go:14-41](file://internal/router/router.go#L14-L41)
- [brand.go:30-35](file://internal/handler/brand.go#L30-L35)
- [brand_repository.go:31-50](file://internal/repository/brand.go#L31-L50)
- [mysql.go:28-46](file://internal/database/mysql.go#L28-L46)
## 详细组件分析
### 表现层(Router/Handler)
- 路由器在入口中被创建,并注入日志、数据库、搜索与 Redis 客户端
- 注册健康检查、品牌、型号、设备等路由组与端点
- 处理器通过构造函数注入数据库连接与日志实例,确保单一职责与可测试性
```mermaid
classDiagram
class Router {
+New(log, db, searchClient, redis) Engine
}
class HealthHandler {
+Check(c)
}
class BrandHandler {
-repo BrandRepository
-log Logger
+GetBrand(c)
}
class ModelHandler {
-repo ModelRepository
-log Logger
+GetModel(c)
}
Router --> HealthHandler : "注册路由"
Router --> BrandHandler : "注册路由"
Router --> ModelHandler : "注册路由"
```
**图示来源**
- [router.go:14-41](file://internal/router/router.go#L14-L41)
- [health.go:8-18](file://internal/handler/health.go#L8-L18)
- [brand.go:14-24](file://internal/handler/brand.go#L14-L24)
- [model.go:14-24](file://internal/handler/model.go#L14-L24)
**章节来源**
- [router.go:14-41](file://internal/router/router.go#L14-L41)
- [health.go:8-18](file://internal/handler/health.go#L8-L18)
- [brand.go:19-24](file://internal/handler/brand.go#L19-L24)
- [model.go:19-24](file://internal/handler/model.go#L19-L24)
### 业务层(Repository)
- 仓库封装数据库查询逻辑,使用上下文传递取消信号与超时控制
- 支持条件查询与排序,将结果映射到领域模型
- 通过构造函数注入数据库连接,保持与底层实现解耦
```mermaid
classDiagram
class BrandRepository {
-db sql.DB
+NewBrandRepository(db)
+List(ctx, brandName) []Brand
}
class BrandModel {
+ID int
+Name string
}
BrandRepository --> BrandModel : "返回领域对象"
```
**图示来源**
- [brand_repository.go:12-50](file://internal/repository/brand.go#L12-L50)
- [brand_model.go:3-6](file://internal/model/brand.go#L3-L6)
**章节来源**
- [brand_repository.go:16-18](file://internal/repository/brand.go#L16-L18)
- [brand_repository.go:20-50](file://internal/repository/brand.go#L20-L50)
- [brand_model.go:3-6](file://internal/model/brand.go#L3-L6)
### 数据访问层(Database/Cache/Search)
- 数据库连接通过 DSN 配置,设置连接池大小与生命周期,并进行健康检查
- Redis 客户端基于配置创建,用于后续缓存操作
- Meilisearch 客户端封装搜索请求,限制检索字段并解码结果
```mermaid
flowchart TD
Start(["初始化数据访问层"]) --> DBInit["创建数据库连接
internal/database/mysql.go"]
DBInit --> DBPool["设置连接池参数"]
DBPool --> DBPing["执行健康检查"]
DBPing --> RedisInit["创建 Redis 客户端
internal/cache/redis.go"]
DBPing --> SearchInit["创建 Meilisearch 客户端
internal/search/meilisearch.go"]
RedisInit --> End(["完成"])
SearchInit --> End
```
**图示来源**
- [mysql.go:14-46](file://internal/database/mysql.go#L14-L46)
- [redis.go:10-16](file://internal/cache/redis.go#L10-L16)
- [meilisearch.go:17-20](file://internal/search/meilisearch.go#L17-L20)
**章节来源**
- [mysql.go:14-46](file://internal/database/mysql.go#L14-L46)
- [redis.go:10-16](file://internal/cache/redis.go#L10-L16)
- [meilisearch.go:17-20](file://internal/search/meilisearch.go#L17-L20)
### 基础设施层(Middleware/Logger)
- 日志中间件记录状态码、路径、耗时、IP、请求 ID 等信息,并按级别输出
- 请求 ID 中间件为每个请求生成唯一标识,便于追踪
- CORS 中间件允许跨域访问
```mermaid
flowchart TD
Req["请求进入"] --> ReqID["生成/获取请求ID"]
ReqID --> LogMW["日志中间件记录"]
LogMW --> CORS["CORS 中间件"]
CORS --> Handler["处理器执行"]
Handler --> Resp["响应返回"]
```
**图示来源**
- [logger_middleware.go:10-45](file://internal/middleware/logger.go#L10-L45)
**章节来源**
- [logger_middleware.go:10-45](file://internal/middleware/logger.go#L10-L45)
### 配置管理(Config)
- 配置加载支持环境变量覆盖,分别加载数据库、Meilisearch、Redis 的配置
- 在生产环境与开发环境之间切换默认值
- 提供地址格式化方法与环境变量读取辅助函数
```mermaid
flowchart TD
Load["加载配置"] --> Env["解析环境变量"]
Env --> DB["加载数据库配置"]
Env --> MS["加载 Meilisearch 配置"]
Env --> RD["加载 Redis 配置"]
DB --> ValidateDB["校验数据库配置"]
MS --> ValidateMS["校验 Meilisearch 配置"]
RD --> ValidateRD["校验 Redis 配置"]
ValidateDB --> Done["返回配置对象"]
ValidateMS --> Done
ValidateRD --> Done
```
**图示来源**
- [config.go:18-56](file://internal/config/config.go#L18-L56)
- [database.go:17-71](file://internal/config/database.go#L17-L71)
- [meilisearch_config.go:14-50](file://internal/config/meilisearch.go#L14-L50)
- [redis_config.go:16-56](file://internal/config/redis.go#L16-L56)
**章节来源**
- [config.go:18-56](file://internal/config/config.go#L18-L56)
- [database.go:17-71](file://internal/config/database.go#L17-L71)
- [meilisearch_config.go:14-50](file://internal/config/meilisearch.go#L14-L50)
- [redis_config.go:16-56](file://internal/config/redis.go#L16-L56)
## 依赖分析
- 入口依赖配置、数据库、缓存与搜索引擎,然后构建路由器
- 路由器依赖中间件与处理器,处理器依赖仓库与日志
- 仓库依赖数据库连接,处理器可选依赖缓存与搜索引擎
- 配置模块独立于业务层,提供环境化参数
```mermaid
graph LR
Main["cmd/server/main.go"] --> Config["internal/config/*"]
Main --> DB["internal/database/mysql.go"]
Main --> Redis["internal/cache/redis.go"]
Main --> Search["internal/search/meilisearch.go"]
Main --> Router["internal/router/router.go"]
Router --> Middleware["internal/middleware/*"]
Router --> Handlers["internal/handler/*"]
Handlers --> Repositories["internal/repository/*"]
Repositories --> DB
Handlers --> Redis
Handlers --> Search
Handlers --> Logger["pkg/logger/*"]
```
**图示来源**
- [main.go:22-64](file://cmd/server/main.go#L22-L64)
- [router.go:14-41](file://internal/router/router.go#L14-L41)
**章节来源**
- [main.go:22-64](file://cmd/server/main.go#L22-L64)
- [router.go:14-41](file://internal/router/router.go#L14-L41)
## 性能考虑
- 数据库连接池:设置最大打开连接数、空闲连接数与连接生命周期,减少连接开销
- 上下文超时:仓库查询使用上下文传递超时,避免阻塞
- 编码优化:处理器支持 Base64 编码响应,降低传输体积但增加 CPU 开销,需按场景权衡
- 中间件顺序:日志中间件应置于末尾以统计真实耗时
[本节为通用指导,无需特定文件来源]
## 故障排除指南
- 数据库连接失败:检查配置中的主机、端口、用户名与密码;确认网络可达与安全组放行
- Meilisearch 搜索异常:确认索引名称与 API Key 正确,检查网络连通性
- Redis 连接问题:核对主机、端口与认证信息,验证目标数据库编号
- 日志输出异常:确认日志初始化成功与环境变量设置正确
- 响应编码错误:当启用 Base64 编码时,确保编码流程无异常并返回合适的状态码
**章节来源**
- [main.go:38-58](file://cmd/server/main.go#L38-L58)
- [brand.go:32-43](file://internal/handler/brand.go#L32-L43)
- [meilisearch.go:27-29](file://internal/search/meilisearch.go#L27-L29)
## 结论
该分层架构通过清晰的职责划分与依赖注入,实现了表现层、业务层、数据访问层与基础设施层的解耦。MVC 变体在本项目中体现为:路由与处理器承担表现层职责,仓库承载业务逻辑,数据库/缓存/搜索引擎作为数据访问层,中间件与日志作为基础设施。建议在扩展新功能时遵循“高层不依赖低层”的原则,保持构造函数注入与接口隔离,持续优化连接池与查询性能,并完善监控与告警体系。