b2c11adeba
- 新增BrandCache与ModelCache,实现多级缓存和TTL管理 - 引入缓存预热机制,启动时自动加载品牌与型号数据 - 实现缓存穿透防护和数据库降级策略,提升服务稳定性 - 优化缓存键命名和数据序列化策略,增强管理便捷性 - 数据访问层新增缓存感知查询,品牌与型号仓库支持缓存优先 - 调整整体架构,增强组件解耦及依赖注入链路清晰度 - 提供详细的性能优化建议和故障排查指南 - 补充监控指标说明,便于后续运维与监控扩展
20 KiB
20 KiB
路由系统
**本文引用的文件** - [router.go](file://internal/router/router.go) - [main.go](file://cmd/server/main.go) - [cors.go](file://internal/middleware/cors.go) - [logger.go](file://internal/middleware/logger.go) - [request_id.go](file://internal/middleware/request_id.go) - [health.go](file://internal/handler/health.go) - [brand.go](file://internal/handler/brand.go) - [model.go](file://internal/handler/model.go) - [model_list.go](file://internal/handler/model_list.go) - [device.go](file://internal/handler/device.go) - [response.go](file://internal/response/response.go) - [config.go](file://internal/config/config.go) - [base64.go](file://pkg/encode/base64.go) - [README.md](file://README.md) - [redis.go](file://internal/cache/redis.go) - [brand_cache.go](file://internal/cache/brand_cache.go) - [model_cache.go](file://internal/cache/model_cache.go) - [brand.go](file://internal/repository/brand.go) - [model.go](file://internal/repository/model.go) - [redis.go](file://internal/config/redis.go) - [meilisearch.go](file://internal/config/meilisearch.go)目录
简介
本文件系统性梳理 Luxsin 应用 API 的路由体系与中间件机制,重点覆盖:
- Gin 路由工厂函数 New 的实现与控制流
- 路由分组策略(/api/v1 与 /audio)
- 中间件执行顺序与职责(CORS、日志、请求 ID)
- 各端点功能、参数与返回规范
- 依赖注入链:缓存与仓库实例的初始化与装配
- 最佳实践与性能优化建议
- 典型调用序列与中间件链路分析
项目结构
路由系统位于 internal/router,入口在 cmd/server/main.go,配合中间件、处理器、统一响应体、缓存与仓库模块协同工作。更新:路由系统现已增强,负责初始化缓存和仓库实例,建立完整的依赖注入链。
graph TB
subgraph "服务入口"
MAIN["cmd/server/main.go<br/>启动 HTTP 服务器"]
ENDSUBGRAPH
subgraph "路由与中间件"
ROUTER["internal/router/router.go<br/>路由工厂与分组注册"]
CORS["internal/middleware/cors.go<br/>CORS 中间件"]
LOGMW["internal/middleware/logger.go<br/>日志中间件"]
REQID["internal/middleware/request_id.go<br/>请求 ID 中间件"]
ENDSUBGRAPH
subgraph "缓存与仓库层"
BRANDCACHE["internal/cache/brand_cache.go<br/>品牌缓存"]
MODELCACHE["internal/cache/model_cache.go<br/>型号缓存"]
BRANDREPO["internal/repository/brand.go<br/>品牌仓库"]
MODELREPO["internal/repository/model.go<br/>型号仓库"]
ENDSUBGRAPH
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"]
ENDSUBGRAPH
subgraph "基础设施"
RESP["internal/response/response.go<br/>统一响应体"]
ENCODE["pkg/encode/base64.go<br/>Base64 编解码"]
CONFIG["internal/config/config.go<br/>配置加载"]
ENDSUBGRAPH
MAIN --> ROUTER
ROUTER --> CORS
ROUTER --> LOGMW
ROUTER --> REQID
ROUTER --> BRANDCACHE
ROUTER --> MODELCACHE
ROUTER --> BRANDREPO
ROUTER --> MODELREPO
ROUTER --> HEALTH
ROUTER --> BRAND
ROUTER --> MODEL
ROUTER --> MODELLIST
ROUTER --> DEVICE
BRAND --> RESP
MODEL --> RESP
MODELLIST --> RESP
DEVICE --> RESP
MODELLIST --> ENCODE
BRAND --> ENCODE
MODEL --> ENCODE
图表来源
- router.go:16-52
- main.go:59-70
- brand_cache.go:18-44
- model_cache.go:19-69
- brand.go:14-52
- model.go:14-79
章节来源
核心组件
- 路由工厂函数 New:集中初始化 Gin 引擎、注册全局中间件、创建各处理器实例,并完成路由分组与注册。更新:现负责初始化缓存和仓库实例,建立完整的依赖注入链。
- 路由分组:
- /api/v1:版本化健康检查端点
- /audio:音频设备相关业务端点
- 中间件链:Recovery -> RequestID -> Logger -> CORS
- 统一响应体:OK/Fail/BadRequest/InternalError,保证一致的返回结构
- 新增:依赖注入链路
- 缓存层:BrandCache、ModelCache
- 仓库层:BrandRepository、ModelRepository
- 处理器层:HealthHandler、BrandHandler、ModelHandler、ModelListHandler、DeviceHandler
章节来源
架构总览
下图展示了从请求进入至响应返回的完整链路,包括中间件执行顺序、依赖注入与处理器调用。
sequenceDiagram
participant C as "客户端"
participant G as "Gin 引擎"
participant R as "路由分组(/api/v1 或 /audio)"
participant M1 as "中间件 : Recovery"
participant M2 as "中间件 : RequestID"
participant M3 as "中间件 : Logger"
participant M4 as "中间件 : CORS"
participant H as "处理器"
C->>G : "HTTP 请求"
G->>M1 : "进入中间件链"
M1->>M2 : "继续"
M2->>M3 : "继续"
M3->>M4 : "继续"
M4->>R : "匹配路由分组"
R->>H : "调用对应处理器"
H-->>G : "写入响应"
G-->>C : "HTTP 响应"
图表来源
详细组件分析
路由工厂与中间件链
- 工厂函数 New 创建 Gin 引擎并按顺序注册中间件,确保异常恢复、请求追踪、日志记录与跨域支持贯穿所有路由。
- 更新:在处理器创建前完成缓存和仓库实例的初始化,形成完整的依赖注入链。
- 中间件顺序决定日志统计的粒度与错误兜底能力,建议保持现有顺序以获得最佳可观测性与稳定性。
章节来源
依赖注入链详解
缓存层初始化
- BrandCache:管理品牌全量数据缓存,键为 "brand:all",TTL 30 分钟
- ModelCache:管理型号数据缓存,支持按品牌和全量两种缓存策略
- 缓存键空间:
- 品牌:brand:all
- 型号按品牌:model:brand:{brand}
- 型号全量:model:all
仓库层初始化
- BrandRepository:封装品牌数据访问,支持缓存优先策略
- ModelRepository:封装型号数据访问,支持多维度缓存策略
- 仓库层具备缓存降级能力,Redis 异常时自动回退到数据库
处理器层初始化
- HealthHandler:健康检查处理器
- BrandHandler:品牌列表处理器,依赖 BrandRepository
- ModelHandler:型号列表处理器,依赖 ModelRepository
- ModelListHandler:型号搜索处理器,依赖 Meilisearch 客户端
- DeviceHandler:设备信息上报处理器,直接依赖 Redis 客户端
章节来源
路由分组与端点清单
- /api/v1 分组
- GET /api/v1/health → 健康检查
- /audio 分组
- GET /audio/getBrand → 品牌列表
- GET /audio/getModel → 型号列表
- GET /audio/modelList → 模型搜索列表
- GET /audio/reportDevInfo → 设备信息上报
章节来源
中间件详解
CORS 中间件
- 设置允许来源、方法、头字段与暴露头
- 对预检请求直接返回状态码
- 放行后续处理器执行
章节来源
日志中间件
- 记录请求路径、方法、耗时、状态码、客户端 IP、请求 ID、查询参数与错误信息
- 按状态码分级输出(info/warn/error)
章节来源
请求 ID 中间件
- 从请求头读取或生成唯一标识,注入上下文并回传给客户端
- 用于全链路追踪与问题定位
章节来源
处理器与端点行为
健康检查 /api/v1/health
- 功能:返回服务运行状态
- 参数:无
- 返回:统一响应体,data 包含状态字段
章节来源
品牌列表 /audio/getBrand
- 功能:按品牌名模糊查询品牌列表
- 查询参数:
- brandName:品牌名称(可选)
- base64Resp:是否返回 Base64 编码结果(默认 true)
- 行为:
- 调用仓库层查询,优先使用缓存
- 缓存未命中时回退到数据库
- 可选地对结果进行 JSON 编码后返回
章节来源
型号列表 /audio/getModel
- 功能:按品牌或型号关键词查询型号列表
- 查询参数:
- brandName:品牌名称(可选)
- modelName:型号名称(可选)
- base64Resp:是否返回 Base64 编码结果(默认 true)
- 行为:
- 调用仓库层查询,支持多种查询策略
- 缓存优先,异常时回退到数据库
- 可选地对结果进行 JSON 编码后返回
章节来源
模型搜索列表 /audio/modelList
- 功能:基于关键字与数量限制进行模型检索
- 查询参数:
- key:搜索关键字
- count:返回条数上限(可选,默认较大值)
- base64Resp:是否返回 Base64 编码结果(默认 true)
- 行为:
- 调用搜索引擎客户端查询
- 可选地对结果进行 JSON 编码后返回
章节来源
设备信息上报 /audio/reportDevInfo
- 功能:接收设备 MAC、型号、版本与来源 IP,写入缓存
- 查询参数:
- mac:设备 MAC 地址(必填)
- model:设备型号(必填)
- ver:版本号(可选)
- 行为:
- 校验必填参数
- 组装设备信息并写入 Redis Hash
- 返回统一响应体
章节来源
统一响应体
- OK:成功响应,code=0,message="ok"
- Fail:通用错误,携带业务 code 与 message
- BadRequest:客户端错误
- InternalError:服务端错误
章节来源
路由注册流程(工厂模式)
- 初始化 Gin 引擎
- 注册全局中间件(Recovery、RequestID、Logger、CORS)
- 新增:初始化缓存实例(BrandCache、ModelCache)
- 新增:初始化仓库实例(BrandRepository、ModelRepository)
- 新增:初始化处理器实例(注入相应依赖)
- 创建路由分组并注册端点
- 返回引擎供 HTTP 服务器使用
flowchart TD
Start(["调用 New"]) --> Init["创建 Gin 引擎"]
Init --> UseRecovery["注册 Recovery 中间件"]
UseRecovery --> UseReqID["注册 RequestID 中间件"]
UseReqID --> UseLogger["注册 Logger 中间件"]
UseLogger --> UseCORS["注册 CORS 中间件"]
UseCORS --> NewCache["初始化缓存实例<br/>BrandCache, ModelCache"]
NewCache --> NewRepo["初始化仓库实例<br/>BrandRepository, ModelRepository"]
NewRepo --> NewHandlers["创建各处理器实例<br/>注入相应依赖"]
NewHandlers --> GroupV1["创建 /api/v1 分组"]
GroupV1 --> RegHealth["注册 /api/v1/health"]
NewHandlers --> GroupAudio["创建 /audio 分组"]
GroupAudio --> RegBrand["注册 /audio/getBrand"]
GroupAudio --> RegModel["注册 /audio/getModel"]
GroupAudio --> RegModelList["注册 /audio/modelList"]
GroupAudio --> RegDevice["注册 /audio/reportDevInfo"]
RegDevice --> ReturnEngine["返回引擎"]
图表来源
依赖关系分析
- 路由层依赖中间件层与处理器层
- 更新:处理器层依赖响应体、编码工具与底层存储
- 更新:仓库层依赖缓存层与数据库连接
- 更新:缓存层依赖 Redis 客户端
- 服务启动层负责装配配置、数据库、搜索引擎与缓存,并将它们注入路由工厂
graph LR
MAIN["cmd/server/main.go"] --> ROUTER["internal/router/router.go"]
ROUTER --> MW_REQID["internal/middleware/request_id.go"]
ROUTER --> MW_LOG["internal/middleware/logger.go"]
ROUTER --> MW_CORS["internal/middleware/cors.go"]
ROUTER --> CACHE["internal/cache/*"]
ROUTER --> REPO["internal/repository/*"]
ROUTER --> H_HEALTH["internal/handler/health.go"]
ROUTER --> H_BRAND["internal/handler/brand.go"]
ROUTER --> H_MODEL["internal/handler/model.go"]
ROUTER --> H_MODELLIST["internal/handler/model_list.go"]
ROUTER --> H_DEVICE["internal/handler/device.go"]
H_BRAND --> RESP["internal/response/response.go"]
H_MODEL --> RESP
H_MODELLIST --> RESP
H_DEVICE --> RESP
H_MODELLIST --> ENCODE["pkg/encode/base64.go"]
H_BRAND --> ENCODE
H_MODEL --> ENCODE
CACHE --> REDIS["Redis 客户端"]
REPO --> DB["MySQL 数据库"]
图表来源
章节来源
性能考量
- 中间件顺序与开销
- Recovery 放在首位,避免重复包裹
- RequestID/CORS/LR 等轻量中间件顺序合理,尽量减少阻塞
- 新增:缓存策略优化
- 品牌全量缓存:brand:all,TTL 30 分钟
- 型号按品牌缓存:model:brand:{brand},TTL 30 分钟
- 型号全量缓存:model:all,TTL 30 分钟
- 缓存降级:Redis 异常时自动回退到数据库
- 新增:预热机制
- 启动时从数据库加载数据到 Redis
- 品牌和型号分别进行全量预热
- 日志中间件
- 建议仅在必要时记录查询参数,避免大对象日志
- 控制错误日志频率,防止雪崩
- 编码优化
- base64Resp 仅在需要时开启,避免不必要的编码成本
- 路由分组
- 将版本化与业务域分离,便于未来扩展与限流策略落地
故障排查指南
- 健康检查失败
- 检查 /api/v1/health 是否可达
- 关注日志中间件输出的状态码与耗时
- 新增:缓存相关问题
- Redis 连接失败:检查 Redis 配置与网络连通性
- 缓存数据异常:验证缓存键空间与 TTL 设置
- 缓存降级:确认数据库连接正常
- 新增:仓库层问题
- SQL 查询超时:检查数据库索引与查询条件
- 仓库初始化失败:确认依赖的缓存和数据库连接正常
- CORS 相关问题
- 确认浏览器预检请求已正确处理
- 核对允许的方法与头字段
- 请求 ID 未返回
- 检查客户端是否正确传递与读取 X-Request-ID
- 处理器错误
- 查看处理器日志中的错误字段
- 使用统一响应体的 code/message 定位问题
- 编码异常
- base64Resp 开启时确认客户端解析逻辑
章节来源
结论
本路由系统采用清晰的工厂模式与中间件链设计,结合版本化与业务域分组,具备良好的可维护性与扩展性。更新:路由系统现已增强,负责初始化缓存和仓库实例,建立了完整的依赖注入链,提升了系统的整体性能与可靠性。遵循现有中间件顺序与统一响应体规范,有助于提升可观测性与稳定性。建议在新增端点时严格复用现有中间件与响应体,确保一致性与性能。
附录
端点一览与参数说明
- /api/v1/health
- 方法:GET
- 参数:无
- 返回:统一响应体
- /audio/getBrand
- 方法:GET
- 参数:
- brandName:字符串(可选)
- base64Resp:布尔或数字字符串(可选,默认 true)
- 返回:统一响应体
- /audio/getModel
- 方法:GET
- 参数:
- brandName:字符串(可选)
- modelName:字符串(可选)
- base64Resp:布尔或数字字符串(可选,默认 true)
- 返回:统一响应体
- /audio/modelList
- 方法:GET
- 参数:
- key:字符串(必填)
- count:整数(可选,默认较大值)
- base64Resp:布尔或数字字符串(可选,默认 true)
- 返回:统一响应体
- /audio/reportDevInfo
- 方法:GET
- 参数:
- mac:字符串(必填)
- model:字符串(必填)
- ver:字符串(可选)
- 返回:统一响应体
章节来源
中间件链路分析(序列图)
sequenceDiagram
participant Client as "客户端"
participant Engine as "Gin 引擎"
participant Recovery as "Recovery"
participant ReqID as "RequestID"
participant Logger as "Logger"
participant CORS as "CORS"
participant Handler as "处理器"
Client->>Engine : "请求"
Engine->>Recovery : "进入"
Recovery->>ReqID : "继续"
ReqID->>Logger : "继续"
Logger->>CORS : "继续"
CORS->>Handler : "匹配路由并调用"
Handler-->>Engine : "写入响应"
Engine-->>Client : "响应"
图表来源
依赖注入链路图
graph TB
subgraph "应用启动"
MAIN["cmd/server/main.go<br/>warmUpCache()"]
ENDSUBGRAPH
subgraph "路由工厂"
ROUTER["internal/router/router.go<br/>New()"]
ENDSUBGRAPH
subgraph "缓存层"
BC["BrandCache<br/>brand:all"]
MC["ModelCache<br/>model:brand:, model:all"]
ENDSUBGRAPH
subgraph "仓库层"
BR["BrandRepository<br/>缓存+数据库"]
MR["ModelRepository<br/>缓存+数据库"]
ENDSUBGRAPH
subgraph "处理器层"
HH["HealthHandler"]
BH["BrandHandler"]
MH["ModelHandler"]
MLH["ModelListHandler"]
DH["DeviceHandler"]
ENDSUBGRAPH
MAIN --> BC
MAIN --> MC
MAIN --> BR
MAIN --> MR
ROUTER --> BC
ROUTER --> MC
ROUTER --> BR
ROUTER --> MR
ROUTER --> BH
ROUTER --> MH
ROUTER --> MLH
ROUTER --> DH
图表来源