Files
cs-note/hzh/Gen2D/15-配置级联机制.md

6.2 KiB
Raw Permalink Blame History

tags, create time
tags create time
config
viper
environment-variables
yaml
deployment
configuration-management
2026-06-03 11:10

15. 配置级联机制

概述

Viper 三层配置级联 — YAML 文件 -> 环境变量 -> 默认值,一处配置随处运行。

正文

配置加载流程

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 配置覆盖默认值。


配置结构体

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_ 前缀 + 大写下划线格式:

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

使用场景

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 原生管理

加载过程详解

sequenceDiagram
    participant Main as main.go
    participant Viper as 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 注入

关联文档