# 分层架构设计 **本文档引用的文件** - [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 变体在本项目中体现为:路由与处理器承担表现层职责,仓库承载业务逻辑,数据库/缓存/搜索引擎作为数据访问层,中间件与日志作为基础设施。建议在扩展新功能时遵循“高层不依赖低层”的原则,保持构造函数注入与接口隔离,持续优化连接池与查询性能,并完善监控与告警体系。