chore(git): 更新.gitignore以忽略新的本地文件
Some checks failed
SonarQube Analysis / sonarqube (push) Has been cancelled

This commit is contained in:
lan
2025-11-30 08:33:17 +08:00
parent 4b4980820f
commit a4b6c5011e
58 changed files with 19353 additions and 0 deletions

View File

@@ -0,0 +1,364 @@
# 数据库配置
<cite>
**本文引用的文件**
- [pkg/config/config.go](file://pkg/config/config.go)
- [pkg/database/postgres.go](file://pkg/database/postgres.go)
- [pkg/database/manager.go](file://pkg/database/manager.go)
- [cmd/server/main.go](file://cmd/server/main.go)
- [start.sh](file://start.sh)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件聚焦 CarrotSkin 项目的数据库连接与连接池配置,系统性说明以下内容:
- 连接参数 database.driver、host、port、username、password、database、ssl_mode、timezone 的用途与默认值来源
- 连接池参数 max_idle_conns、max_open_conns、conn_max_lifetime 的工作机制与性能影响
- 如何通过 DATABASE_* 环境变量覆盖默认配置
- 结合 DatabaseConfig 结构体与数据库初始化流程的最佳实践,包含生产环境安全建议与连接池调优策略
## 项目结构
数据库相关能力由配置层与数据库层协同实现:
- 配置层负责加载默认值、绑定环境变量映射,并支持从环境变量覆盖连接池参数
- 数据库层负责根据配置构建 DSN、初始化 GORM 连接、设置连接池并进行连通性测试
- 应用入口在启动时加载配置、初始化数据库并执行迁移
```mermaid
graph TB
subgraph "配置层"
CFG["pkg/config/config.go<br/>DatabaseConfig/默认值/环境映射"]
end
subgraph "数据库层"
DBM["pkg/database/manager.go<br/>Init/GetDB/AutoMigrate/Close"]
PG["pkg/database/postgres.go<br/>New/GetDSN"]
end
subgraph "应用入口"
MAIN["cmd/server/main.go<br/>加载配置/初始化数据库/迁移"]
end
ENV["环境变量<br/>DATABASE_*"]
ENV --> CFG
CFG --> DBM
DBM --> PG
MAIN --> CFG
MAIN --> DBM
```
图表来源
- [pkg/config/config.go](file://pkg/config/config.go#L135-L188)
- [pkg/database/manager.go](file://pkg/database/manager.go#L22-L50)
- [pkg/database/postgres.go](file://pkg/database/postgres.go#L13-L60)
- [cmd/server/main.go](file://cmd/server/main.go#L27-L50)
章节来源
- [pkg/config/config.go](file://pkg/config/config.go#L135-L188)
- [pkg/database/manager.go](file://pkg/database/manager.go#L22-L50)
- [pkg/database/postgres.go](file://pkg/database/postgres.go#L13-L60)
- [cmd/server/main.go](file://cmd/server/main.go#L27-L50)
## 核心组件
- DatabaseConfig 结构体:承载数据库连接与连接池配置
- 配置加载与覆盖:默认值、环境变量映射、连接池参数覆盖
- 数据库初始化:构建 DSN、初始化 GORM、设置连接池、Ping 测试
- 应用启动流程:加载配置 → 初始化数据库 → 自动迁移
章节来源
- [pkg/config/config.go](file://pkg/config/config.go#L34-L47)
- [pkg/config/config.go](file://pkg/config/config.go#L135-L188)
- [pkg/config/config.go](file://pkg/config/config.go#L190-L210)
- [pkg/config/config.go](file://pkg/config/config.go#L238-L280)
- [pkg/database/postgres.go](file://pkg/database/postgres.go#L13-L60)
- [pkg/database/manager.go](file://pkg/database/manager.go#L22-L50)
- [cmd/server/main.go](file://cmd/server/main.go#L27-L50)
## 架构总览
下图展示从配置到数据库连接的关键调用链路与职责分工。
```mermaid
sequenceDiagram
participant Entrypoint as "应用入口(main.go)"
participant Cfg as "配置(Config.Load)"
participant DBMgr as "数据库管理器(database.Init)"
participant DB as "数据库(New)"
participant SQL as "底层sql.DB"
Entrypoint->>Cfg : "加载配置"
Cfg-->>Entrypoint : "返回完整配置"
Entrypoint->>DBMgr : "Init(DatabaseConfig)"
DBMgr->>DB : "New(DatabaseConfig)"
DB->>DB : "构造DSN"
DB->>SQL : "gorm.Open + 获取*sql.DB"
DB->>SQL : "SetMaxIdleConns/SetMaxOpenConns/SetConnMaxLifetime"
DB->>SQL : "Ping() 测试连接"
DB-->>DBMgr : "*gorm.DB"
DBMgr-->>Entrypoint : "初始化完成"
```
图表来源
- [cmd/server/main.go](file://cmd/server/main.go#L27-L50)
- [pkg/config/config.go](file://pkg/config/config.go#L108-L133)
- [pkg/database/manager.go](file://pkg/database/manager.go#L22-L33)
- [pkg/database/postgres.go](file://pkg/database/postgres.go#L13-L60)
## 详细组件分析
### DatabaseConfig 字段与用途
- database.driver
- 作用:驱动类型标识,用于控制日志级别与后续扩展点
- 默认值:来自默认配置
- 环境变量映射DATABASE_DRIVER
- database.host
- 作用:数据库主机地址
- 默认值:来自默认配置
- 环境变量映射DATABASE_HOST
- database.port
- 作用:数据库端口
- 默认值:来自默认配置
- 环境变量映射DATABASE_PORT
- database.username
- 作用:数据库用户名
- 默认值:来自默认配置
- 环境变量映射DATABASE_USERNAME
- database.password
- 作用:数据库密码
- 默认值:来自默认配置
- 环境变量映射DATABASE_PASSWORD
- database.database
- 作用:数据库名
- 默认值:来自默认配置
- 环境变量映射DATABASE_NAME
- database.ssl_mode
- 作用SSL 模式(如 disable/require 等),影响 TLS 连接
- 默认值:来自默认配置
- 环境变量映射DATABASE_SSL_MODE
- database.timezone
- 作用:时区设置,影响时间字段的时区行为
- 默认值:来自默认配置
- 环境变量映射DATABASE_TIMEZONE
章节来源
- [pkg/config/config.go](file://pkg/config/config.go#L34-L47)
- [pkg/config/config.go](file://pkg/config/config.go#L135-L188)
- [pkg/config/config.go](file://pkg/config/config.go#L190-L210)
### 连接池配置项与工作机制
- max_idle_conns
- 作用:最大空闲连接数,控制连接池中空闲连接上限
- 默认值:来自默认配置
- 环境变量覆盖DATABASE_MAX_IDLE_CONNS
- max_open_conns
- 作用:最大打开连接数,限制并发连接上限
- 默认值:来自默认配置
- 环境变量覆盖DATABASE_MAX_OPEN_CONNS
- conn_max_lifetime
- 作用:连接最大存活时间,到期后连接会被回收
- 默认值:来自默认配置
- 环境变量覆盖DATABASE_CONN_MAX_LIFETIME支持时长字符串如“1h”
这些参数在 New 中通过底层 sql.DB 设置,并在 Ping 成功后生效。
章节来源
- [pkg/config/config.go](file://pkg/config/config.go#L34-L47)
- [pkg/config/config.go](file://pkg/config/config.go#L135-L188)
- [pkg/config/config.go](file://pkg/config/config.go#L238-L280)
- [pkg/database/postgres.go](file://pkg/database/postgres.go#L49-L53)
### 环境变量覆盖与默认值
- 默认值来源
- 通过 viper.SetDefault 设置,确保即使未提供对应环境变量也能有合理默认
- 环境变量映射
- 使用 viper.BindEnv 将配置键映射到 DATABASE_* 前缀的环境变量
- 连接池参数覆盖
- 通过 overrideFromEnv 从环境变量读取整型或时长字符串并覆盖默认值
章节来源
- [pkg/config/config.go](file://pkg/config/config.go#L135-L188)
- [pkg/config/config.go](file://pkg/config/config.go#L190-L210)
- [pkg/config/config.go](file://pkg/config/config.go#L238-L280)
### 数据库初始化流程与 DSN 构造
- DSN 构造
- New 中依据 DatabaseConfig 组装 DSN包含 host、port、user、password、dbname、sslmode、TimeZone
- GORM 初始化
- 根据 driver 决定日志级别;禁用迁移时的外键约束以避免循环依赖
- 连接池设置
- SetMaxIdleConns、SetMaxOpenConns、SetConnMaxLifetime
- 连通性测试
- Ping 成功后返回 gorm.DB 实例
章节来源
- [pkg/database/postgres.go](file://pkg/database/postgres.go#L13-L60)
### 应用启动中的数据库初始化
- 配置加载Load 会加载 .env 并解析为 Config
- 数据库初始化Init 接收 DatabaseConfig内部调用 New 完成连接与池设置
- 自动迁移AutoMigrate 按顺序迁移模型,确保外键依赖关系正确
- 资源清理Close 关闭底层 sql.DB
章节来源
- [cmd/server/main.go](file://cmd/server/main.go#L27-L50)
- [pkg/database/manager.go](file://pkg/database/manager.go#L22-L50)
- [pkg/database/manager.go](file://pkg/database/manager.go#L52-L99)
- [pkg/database/manager.go](file://pkg/database/manager.go#L101-L114)
## 依赖关系分析
```mermaid
classDiagram
class Config {
+ServerConfig Server
+DatabaseConfig Database
+RedisConfig Redis
+RustFSConfig RustFS
+JWTConfig JWT
+CasbinConfig Casbin
+LogConfig Log
+UploadConfig Upload
+EmailConfig Email
}
class DatabaseConfig {
+string Driver
+string Host
+int Port
+string Username
+string Password
+string Database
+string SSLMode
+string Timezone
+int MaxIdleConns
+int MaxOpenConns
+duration ConnMaxLifetime
}
class Manager {
+Init(cfg, logger) error
+GetDB() (*gorm.DB, error)
+MustGetDB() *gorm.DB
+AutoMigrate(logger) error
+Close() error
}
class Postgres {
+New(cfg) (*gorm.DB, error)
+GetDSN(cfg) string
}
Config --> DatabaseConfig : "包含"
Manager --> DatabaseConfig : "使用"
Postgres --> DatabaseConfig : "使用"
Manager --> Postgres : "调用"
```
图表来源
- [pkg/config/config.go](file://pkg/config/config.go#L13-L24)
- [pkg/config/config.go](file://pkg/config/config.go#L34-L47)
- [pkg/database/manager.go](file://pkg/database/manager.go#L22-L50)
- [pkg/database/postgres.go](file://pkg/database/postgres.go#L13-L60)
## 性能考量
- 连接池参数建议
- max_idle_conns建议与 max_open_conns 保持一定比例,避免过多空闲连接占用资源
- max_open_conns应结合数据库最大连接数与应用并发量综合评估避免超过数据库限制导致连接排队
- conn_max_lifetime建议设置为小于数据库连接超时阈值确保连接健康与复用效率
- 日志级别
- 当 driver 为 postgres 时GORM 日志级别提升为 Info便于调试在生产环境可考虑降低日志级别以减少开销
- 迁移策略
- AutoMigrate 顺序需保证被引用表先于引用表创建,避免外键约束冲突
章节来源
- [pkg/database/postgres.go](file://pkg/database/postgres.go#L25-L32)
- [pkg/database/manager.go](file://pkg/database/manager.go#L52-L99)
## 故障排查指南
- 未初始化即使用数据库
- 现象:调用 GetDB 返回错误提示“数据库未初始化”
- 处理:确保在应用启动阶段先调用 database.Init
- 连接失败
- 检查 DSN 参数是否正确host/port/username/password/database/ssl_mode/timezone
- 确认数据库可达与凭据有效
- 连接池异常
- 检查 max_idle_conns、max_open_conns 是否设置过小或过大
- 检查 conn_max_lifetime 是否导致频繁重建连接
- 环境变量未生效
- 确认环境变量前缀与键名匹配DATABASE_*
- 确认 overrideFromEnv 可正确解析整型与 duration 类型
章节来源
- [pkg/database/manager.go](file://pkg/database/manager.go#L35-L41)
- [pkg/database/postgres.go](file://pkg/database/postgres.go#L13-L60)
- [pkg/config/config.go](file://pkg/config/config.go#L190-L210)
- [pkg/config/config.go](file://pkg/config/config.go#L238-L280)
## 结论
- CarrotSkin 的数据库配置采用“默认值 + 环境变量覆盖”的设计,既保证开箱即用,又允许灵活定制
- 连接池参数通过 DATABASE_MAX_IDLE_CONNS、DATABASE_MAX_OPEN_CONNS、DATABASE_CONN_MAX_LIFETIME 进行覆盖,建议结合业务并发与数据库能力进行调优
- 生产环境建议启用 SSLssl_mode、严格凭据管理与最小权限原则并适当降低日志级别以优化性能
## 附录
### 环境变量与默认值对照表
- database.driver
- 环境变量DATABASE_DRIVER
- 默认值postgres
- database.host
- 环境变量DATABASE_HOST
- 默认值localhost
- database.port
- 环境变量DATABASE_PORT
- 默认值5432
- database.username
- 环境变量DATABASE_USERNAME
- 默认值:空字符串
- database.password
- 环境变量DATABASE_PASSWORD
- 默认值:空字符串
- database.database
- 环境变量DATABASE_NAME
- 默认值:空字符串
- database.ssl_mode
- 环境变量DATABASE_SSL_MODE
- 默认值disable
- database.timezone
- 环境变量DATABASE_TIMEZONE
- 默认值Asia/Shanghai
- database.max_idle_conns
- 环境变量DATABASE_MAX_IDLE_CONNS
- 默认值10
- database.max_open_conns
- 环境变量DATABASE_MAX_OPEN_CONNS
- 默认值100
- database.conn_max_lifetime
- 环境变量DATABASE_CONN_MAX_LIFETIME
- 默认值1h
章节来源
- [pkg/config/config.go](file://pkg/config/config.go#L135-L188)
- [pkg/config/config.go](file://pkg/config/config.go#L190-L210)
- [pkg/config/config.go](file://pkg/config/config.go#L238-L280)
### 生产环境安全与连接池调优建议
- 安全建议
- 将 ssl_mode 设为 require 或 verify-full视数据库支持而定并配合证书校验
- 使用专用数据库用户与最小权限策略,定期轮换密码
- 通过环境变量注入敏感信息,避免硬编码
- 连接池调优
- 初步以 max_idle_conns ≈ 1/10 max_open_conns 开始,结合压测结果调整
- 将 conn_max_lifetime 设置为略小于数据库连接超时阈值,平衡资源回收与连接复用
- 监控数据库连接数与等待队列,动态调整 max_open_conns
章节来源
- [pkg/config/config.go](file://pkg/config/config.go#L135-L188)
- [pkg/config/config.go](file://pkg/config/config.go#L238-L280)
- [pkg/database/postgres.go](file://pkg/database/postgres.go#L49-L53)
### 启动脚本中的数据库环境变量示例
- 示例脚本展示了如何设置 DATABASE_HOST、DATABASE_PORT、DATABASE_USERNAME、DATABASE_PASSWORD、DATABASE_NAME、DATABASE_SSL_MODE、DATABASE_TIMEZONE 等环境变量
章节来源
- [start.sh](file://start.sh#L1-L41)