# 15. 配置级联机制 > **一句话概括**:Viper 三层配置级联 — YAML 文件 -> 环境变量 -> 默认值,一处配置随处运行。 --- ## 配置加载流程 ```mermaid flowchart LR subgraph "配置源(优先级从低到高)" D["默认值\nsetDefaults()"] Y["YAML 文件\nconfig.yaml"] E["环境变量\n.env / system env"] end subgraph "Viper 引擎" V["Viper\n合并 + 覆盖"] end subgraph "输出" C["Config Struct\n全局配置对象"] S["各组件\nServer / DB / Redis / ..."] end D -->|"1. 设置默认值"| V Y -->|"2. 读取 YAML"| V E -->|"3. 绑定 ENV"| V V -->|"Unmarshal"| C C -->|"注入"| S style D fill:#9e9e9e,stroke:#333,color:#fff style Y fill:#2196f3,stroke:#333,color:#fff style E fill:#f44336,stroke:#333,color:#fff style V fill:#ff9800,stroke:#333,color:#fff ``` **优先级规则**:`ENV > YAML > Default` 环境变量始终拥有最高优先级,可以覆盖任何 YAML 配置;YAML 配置覆盖默认值。 --- ## 配置结构体 ```go type Config struct { Server ServerConfig // HTTP 服务 Database DatabaseConfig // MySQL 数据库 JWT JWTConfig // JWT 签名 Log LogConfig // 日志 Redis RedisConfig // Redis 缓存 LLM LLMConfig // 大语言模型 ImageGen ImageGenConfig // 文生图 API Qiniu QiniuConfig // 七牛云存储 WorkerPool WorkerPoolConfig // 协程池 TaskQueue TaskQueueConfig // 任务队列 } ``` | 配置块 | 关键字段 | 默认值 | |--------|----------|--------| | `Server` | `port`, `mode` | `8080`, `debug` | | `Database` | `dsn` | `gen2d:password@tcp(127.0.0.1:3306)/gen2d` | | `JWT` | `secret`, `expire` | `gen2d-dev-secret`, `7200s` | | `Log` | `level`, `format` | `info`, `text` | | `Redis` | `addr`, `password`, `db` | `localhost:6379`, `""`, `0` | | `LLM` | `base_url`, `api_key`, `model` | `api.openai.com/v1`, `""`, `gpt-4o` | | `ImageGen` | `base_url`, `model`, `timeout` | `api.suchuang.vip/v1`, `gpt-image-2-token`, `120s` | | `Qiniu` | `bucket`, `cdn_host`, `url_expire` | `""`, `""`, `3600s` | | `WorkerPool` | `workers`, `queue_size`, `max_per_user` | `NumCPU*4`, `100`, `2` | | `TaskQueue` | `driver`, `memory.buffer_size` | `memory`, `100` | --- ## 环境变量绑定 每个配置字段都有对应的环境变量绑定,命名规则为 `GEN2D_` 前缀 + 大写下划线格式: ```go func bindEnvVars(v *viper.Viper) { v.BindEnv("server.port", "GEN2D_PORT") v.BindEnv("server.mode", "GEN2D_MODE") v.BindEnv("database.dsn", "GEN2D_DSN") v.BindEnv("jwt.secret", "GEN2D_JWT_SECRET") v.BindEnv("llm.api_key", "GEN2D_LLM_API_KEY") v.BindEnv("redis.addr", "GEN2D_REDIS_ADDR") v.BindEnv("qiniu.access_key", "GEN2D_QINIU_ACCESS_KEY") // ... 共 25+ 个绑定 } ``` | 配置路径 | 环境变量 | 说明 | |----------|----------|------| | `server.port` | `GEN2D_PORT` | HTTP 端口 | | `server.mode` | `GEN2D_MODE` | `debug` / `release` | | `database.dsn` | `GEN2D_DSN` | MySQL 连接串 | | `jwt.secret` | `GEN2D_JWT_SECRET` | JWT 签名密钥 | | `llm.base_url` | `GEN2D_LLM_BASE_URL` | LLM API 地址 | | `llm.api_key` | `GEN2D_LLM_API_KEY` | LLM API 密钥 | | `image_gen.base_url` | `GEN2D_IMAGE_BASE_URL` | 文生图 API 地址 | | `redis.addr` | `GEN2D_REDIS_ADDR` | Redis 地址 | | `taskqueue.driver` | `GEN2D_TASKQUEUE_DRIVER` | `memory` / `rabbitmq` | --- ## 使用场景 ```mermaid flowchart TD subgraph "开发环境" D1["config.yaml\n本地配置文件"] D2[".env\n环境变量覆盖敏感值"] D3["默认值\n开箱即用"] end subgraph "测试环境" T1["环境变量\nCI/CD 管线注入"] T2["默认值\n兜底"] end subgraph "生产环境" P1["K8s ConfigMap\n非敏感配置"] P2["K8s Secret\n敏感配置(密钥、DSN)"] P3["默认值\n兜底"] end D1 --> D3 D2 --> D1 T1 --> T2 P1 --> P3 P2 --> P1 ``` | 环境 | 主配置源 | 敏感配置 | 说明 | |------|----------|----------|------| | 开发 | `config.yaml` | `.env` 文件 | 直观、可版本控制 | | 测试 | 环境变量 | 环境变量 | CI/CD 管线注入 | | 生产 | ConfigMap | Secret | K8s 原生管理 | --- ## 加载过程详解 ```mermaid sequenceDiagram participant Main as main.go participant Viper participant YAML as config.yaml participant ENV as 环境变量 participant Cfg as Config Struct Main->>Viper: Load() Main->>Viper: setDefaults(v) Note over Viper: 设置 25+ 默认值 Viper->>YAML: ReadInConfig() YAML-->>Viper: 配置内容 Viper->>Viper: bindEnvVars(v) Note over Viper: 绑定 25+ 环境变量 Viper->>ENV: 读取环境变量 ENV-->>Viper: 覆盖对应字段 Viper->>Cfg: Unmarshal(&cfg) Cfg-->>Main: 返回完整配置 ``` 关键步骤: 1. **加载 `.env` 文件** — `godotenv.Load()` 从项目根目录读取 `.env` 2. **设置默认值** — `setDefaults(v)` 为所有字段提供合理的默认值 3. **读取 YAML** — `v.ReadInConfig()` 从 `internal/config/config.yaml` 加载 4. **绑定环境变量** — `bindEnvVars(v)` 将每个字段映射到 `GEN2D_*` 环境变量 5. **反序列化** — `v.Unmarshal(&cfg)` 将合并后的配置映射到 Go 结构体 > **容错设计**:YAML 文件不存在时不报错,仅使用环境变量 + 默认值。这确保了零配置即可启动。 --- ## 与部署的关系 配置级联机制与部署架构紧密配合: | 部署方式 | 配置策略 | 示例 | |----------|----------|------| | `go run` 本地开发 | YAML + `.env` | `config.yaml` 配置 DB,`.env` 配置 API Key | | `docker compose` | `.env` 文件注入 | `env_file: ./backend/.env` | | Kubernetes | ConfigMap + Secret | `GEN2D_DSN` 从 Secret 注入 | --- ## 关联文档 | 文档 | 关系 | |------|------| | [14 - 部署架构](14-deployment.md) | 配置管理在部署中的应用 | | [01 - 系统总览](01-system-overview.md) | 配置在启动流程中的位置 | | [02 - 协程池](02-worker-pool.md) | WorkerPoolConfig 控制并发参数 | | [00 - 索引](00-index.md) | 返回文档总览 |