init
This commit is contained in:
165
serve/config/README.md
Normal file
165
serve/config/README.md
Normal file
@@ -0,0 +1,165 @@
|
||||
# 配置文件说明
|
||||
|
||||
## 多环境配置
|
||||
|
||||
本项目支持多环境配置,通过 `GO_ENV` 环境变量自动选择对应的配置文件。
|
||||
|
||||
### 环境配置文件
|
||||
|
||||
- `config.dev.yaml` - 开发环境配置
|
||||
- `config.prod.yaml` - 生产环境配置
|
||||
- `config.staging.yaml` - 预发布环境配置(可选)
|
||||
- `config.test.yaml` - 测试环境配置(可选)
|
||||
- `config.yaml` - 默认配置文件(回退)
|
||||
|
||||
### 使用方法
|
||||
|
||||
#### 1. 开发环境(默认)
|
||||
|
||||
```bash
|
||||
# 不设置 GO_ENV,默认使用开发环境
|
||||
go run main.go
|
||||
|
||||
# 或显式设置
|
||||
GO_ENV=development go run main.go
|
||||
GO_ENV=dev go run main.go
|
||||
```
|
||||
|
||||
使用配置文件:`config.dev.yaml`
|
||||
|
||||
#### 2. 生产环境
|
||||
|
||||
```bash
|
||||
GO_ENV=production go run main.go
|
||||
# 或
|
||||
GO_ENV=prod go run main.go
|
||||
```
|
||||
|
||||
使用配置文件:`config.prod.yaml`
|
||||
|
||||
#### 3. 预发布环境
|
||||
|
||||
```bash
|
||||
GO_ENV=staging go run main.go
|
||||
# 或
|
||||
GO_ENV=stage go run main.go
|
||||
```
|
||||
|
||||
使用配置文件:`config.staging.yaml`
|
||||
|
||||
#### 4. 测试环境
|
||||
|
||||
```bash
|
||||
GO_ENV=test go run main.go
|
||||
```
|
||||
|
||||
使用配置文件:`config.test.yaml`
|
||||
|
||||
### Windows PowerShell 设置环境变量
|
||||
|
||||
```powershell
|
||||
# 临时设置(仅当前会话)
|
||||
$env:GO_ENV="production"
|
||||
go run main.go
|
||||
|
||||
# 或一行命令
|
||||
$env:GO_ENV="production"; go run main.go
|
||||
```
|
||||
|
||||
### Windows CMD 设置环境变量
|
||||
|
||||
```cmd
|
||||
# 临时设置
|
||||
set GO_ENV=production
|
||||
go run main.go
|
||||
|
||||
# 或一行命令
|
||||
set GO_ENV=production && go run main.go
|
||||
```
|
||||
|
||||
### Linux/Mac 设置环境变量
|
||||
|
||||
```bash
|
||||
# 临时设置
|
||||
export GO_ENV=production
|
||||
go run main.go
|
||||
|
||||
# 或一行命令
|
||||
GO_ENV=production go run main.go
|
||||
```
|
||||
|
||||
## 环境变量覆盖
|
||||
|
||||
敏感配置项可以通过环境变量覆盖,优先级高于配置文件:
|
||||
|
||||
- `DB_PASSWORD` - 数据库密码
|
||||
- `JWT_SECRET` - JWT 密钥
|
||||
- `REDIS_PASSWORD` - Redis 密码
|
||||
|
||||
示例:
|
||||
|
||||
```bash
|
||||
# Linux/Mac
|
||||
export DB_PASSWORD="your_secure_password"
|
||||
export JWT_SECRET="your_jwt_secret_key"
|
||||
GO_ENV=production go run main.go
|
||||
|
||||
# Windows PowerShell
|
||||
$env:DB_PASSWORD="your_secure_password"
|
||||
$env:JWT_SECRET="your_jwt_secret_key"
|
||||
$env:GO_ENV="production"
|
||||
go run main.go
|
||||
```
|
||||
|
||||
## 配置文件优先级
|
||||
|
||||
1. 环境变量(最高优先级)
|
||||
2. 环境特定配置文件(如 `config.prod.yaml`)
|
||||
3. 默认配置文件(`config.yaml`)
|
||||
4. 代码中的默认值(最低优先级)
|
||||
|
||||
## 首次使用
|
||||
|
||||
1. 复制 `config.example.yaml` 为 `config.yaml`
|
||||
2. 修改 `config.yaml` 中的配置项
|
||||
3. 运行应用
|
||||
|
||||
```bash
|
||||
# Windows
|
||||
copy config.example.yaml config.yaml
|
||||
|
||||
# Linux/Mac
|
||||
cp config.example.yaml config.yaml
|
||||
```
|
||||
|
||||
## 生产环境部署建议
|
||||
|
||||
1. ✅ 不要将包含敏感信息的配置文件提交到版本控制
|
||||
2. ✅ 使用环境变量设置所有敏感配置
|
||||
3. ✅ 在生产环境使用 `config.prod.yaml`
|
||||
4. ✅ 确保 JWT Secret 使用强随机字符串
|
||||
5. ✅ 数据库密码使用环境变量而不是写在配置文件中
|
||||
|
||||
## .gitignore 建议
|
||||
|
||||
```gitignore
|
||||
# 配置文件
|
||||
config/config.yaml
|
||||
config/config.*.yaml
|
||||
!config/config.example.yaml
|
||||
|
||||
# 日志文件
|
||||
logs/
|
||||
*.log
|
||||
```
|
||||
|
||||
## 配置验证
|
||||
|
||||
启动时会在日志中显示加载的配置信息:
|
||||
|
||||
```
|
||||
Loaded configuration for environment: production (file: config.prod.yaml)
|
||||
Server mode: release, App environment: production
|
||||
```
|
||||
|
||||
确认配置加载正确后再继续使用。
|
||||
40
serve/config/config.dev.yaml
Normal file
40
serve/config/config.dev.yaml
Normal file
@@ -0,0 +1,40 @@
|
||||
# AI英语学习平台 - 开发环境配置
|
||||
|
||||
server:
|
||||
port: "8080"
|
||||
mode: "debug" # debug, release, test
|
||||
|
||||
database:
|
||||
host: "localhost"
|
||||
port: "3306"
|
||||
user: "root"
|
||||
password: "JKjk20011115" # 建议通过环境变量 DB_PASSWORD 设置
|
||||
dbname: "ai_english_learning"
|
||||
charset: "utf8mb4"
|
||||
|
||||
jwt:
|
||||
secret: "dev-secret-key-change-in-production" # 建议通过环境变量 JWT_SECRET 设置
|
||||
access_token_ttl: 3600 # 1小时
|
||||
refresh_token_ttl: 604800 # 7天
|
||||
|
||||
redis:
|
||||
host: "localhost"
|
||||
port: "6379"
|
||||
password: "" # 建议通过环境变量 REDIS_PASSWORD 设置
|
||||
db: 0
|
||||
|
||||
app:
|
||||
name: "AI English Learning"
|
||||
version: "1.0.0"
|
||||
environment: "development"
|
||||
log_level: "debug"
|
||||
|
||||
log:
|
||||
level: "debug" # debug, info, warn, error, fatal, panic
|
||||
format: "text" # json, text
|
||||
output: "both" # console, file, both
|
||||
file_path: "./logs/dev.log"
|
||||
max_size: 100 # MB
|
||||
max_backups: 5
|
||||
max_age: 7 # days
|
||||
compress: false
|
||||
41
serve/config/config.example.yaml
Normal file
41
serve/config/config.example.yaml
Normal file
@@ -0,0 +1,41 @@
|
||||
# AI英语学习平台配置文件示例
|
||||
# 复制此文件为 config.yaml 或 config.dev.yaml 并修改相应配置
|
||||
|
||||
server:
|
||||
port: "8080"
|
||||
mode: "debug" # debug, release, test
|
||||
|
||||
database:
|
||||
host: "localhost"
|
||||
port: "3306"
|
||||
user: "root"
|
||||
password: "your_password_here" # 建议通过环境变量 DB_PASSWORD 设置
|
||||
dbname: "ai_english_learning"
|
||||
charset: "utf8mb4"
|
||||
|
||||
jwt:
|
||||
secret: "your_jwt_secret_key_here" # 建议通过环境变量 JWT_SECRET 设置
|
||||
access_token_ttl: 3600 # 1小时
|
||||
refresh_token_ttl: 604800 # 7天
|
||||
|
||||
redis:
|
||||
host: "localhost"
|
||||
port: "6379"
|
||||
password: "" # 建议通过环境变量 REDIS_PASSWORD 设置
|
||||
db: 0
|
||||
|
||||
app:
|
||||
name: "AI English Learning"
|
||||
version: "1.0.0"
|
||||
environment: "development" # development, staging, production
|
||||
log_level: "info" # debug, info, warn, error
|
||||
|
||||
log:
|
||||
level: "info" # debug, info, warn, error, fatal, panic
|
||||
format: "json" # json, text
|
||||
output: "both" # console, file, both
|
||||
file_path: "./logs/app.log"
|
||||
max_size: 100 # MB
|
||||
max_backups: 10
|
||||
max_age: 30 # days
|
||||
compress: true
|
||||
160
serve/config/config.go
Normal file
160
serve/config/config.go
Normal file
@@ -0,0 +1,160 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Server ServerConfig `mapstructure:"server"`
|
||||
Database DatabaseConfig `mapstructure:"database"`
|
||||
JWT JWTConfig `mapstructure:"jwt"`
|
||||
Redis RedisConfig `mapstructure:"redis"`
|
||||
App AppConfig `mapstructure:"app"`
|
||||
Log LogConfig `mapstructure:"log"`
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
Port string `mapstructure:"port"`
|
||||
Mode string `mapstructure:"mode"`
|
||||
}
|
||||
|
||||
type DatabaseConfig struct {
|
||||
Host string `mapstructure:"host"`
|
||||
Port string `mapstructure:"port"`
|
||||
User string `mapstructure:"user"`
|
||||
Password string `mapstructure:"password"`
|
||||
DBName string `mapstructure:"dbname"`
|
||||
Charset string `mapstructure:"charset"`
|
||||
}
|
||||
|
||||
type JWTConfig struct {
|
||||
Secret string `mapstructure:"secret"`
|
||||
AccessTokenTTL int `mapstructure:"access_token_ttl"`
|
||||
RefreshTokenTTL int `mapstructure:"refresh_token_ttl"`
|
||||
}
|
||||
|
||||
type RedisConfig struct {
|
||||
Host string `mapstructure:"host"`
|
||||
Port string `mapstructure:"port"`
|
||||
Password string `mapstructure:"password"`
|
||||
DB int `mapstructure:"db"`
|
||||
}
|
||||
|
||||
type AppConfig struct {
|
||||
Name string `mapstructure:"name"`
|
||||
Version string `mapstructure:"version"`
|
||||
Environment string `mapstructure:"environment"`
|
||||
LogLevel string `mapstructure:"log_level"`
|
||||
}
|
||||
|
||||
type LogConfig struct {
|
||||
Level string `mapstructure:"level"`
|
||||
Format string `mapstructure:"format"`
|
||||
Output string `mapstructure:"output"`
|
||||
FilePath string `mapstructure:"file_path"`
|
||||
MaxSize int `mapstructure:"max_size"`
|
||||
MaxBackups int `mapstructure:"max_backups"`
|
||||
MaxAge int `mapstructure:"max_age"`
|
||||
Compress bool `mapstructure:"compress"`
|
||||
}
|
||||
|
||||
var GlobalConfig *Config
|
||||
|
||||
func LoadConfig() {
|
||||
// 获取环境变量,默认为 development
|
||||
env := os.Getenv("GO_ENV")
|
||||
if env == "" {
|
||||
env = "development"
|
||||
}
|
||||
|
||||
// 根据环境选择配置文件
|
||||
configName := getConfigName(env)
|
||||
|
||||
viper.SetConfigName(configName)
|
||||
viper.SetConfigType("yaml")
|
||||
viper.AddConfigPath("./config")
|
||||
viper.AddConfigPath(".")
|
||||
|
||||
// 设置环境变量前缀
|
||||
viper.SetEnvPrefix("AI_ENGLISH")
|
||||
viper.AutomaticEnv()
|
||||
|
||||
// 设置默认值
|
||||
setDefaults()
|
||||
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
log.Printf("Warning: Config file '%s' not found, trying fallback...", configName)
|
||||
// 尝试加载默认配置文件
|
||||
viper.SetConfigName("config")
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
log.Printf("Warning: Default config file not found, using defaults and environment variables: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
GlobalConfig = &Config{}
|
||||
if err := viper.Unmarshal(GlobalConfig); err != nil {
|
||||
log.Fatalf("Unable to decode config: %v", err)
|
||||
}
|
||||
|
||||
// 从环境变量覆盖敏感配置
|
||||
overrideFromEnv()
|
||||
|
||||
log.Printf("Loaded configuration for environment: %s (file: %s.yaml)", env, configName)
|
||||
log.Printf("Server mode: %s, App environment: %s", GlobalConfig.Server.Mode, GlobalConfig.App.Environment)
|
||||
}
|
||||
|
||||
// getConfigName 根据环境返回配置文件名
|
||||
func getConfigName(env string) string {
|
||||
switch env {
|
||||
case "production", "prod":
|
||||
return "config.prod"
|
||||
case "development", "dev":
|
||||
return "config.dev"
|
||||
case "staging", "stage":
|
||||
return "config.staging"
|
||||
case "test":
|
||||
return "config.test"
|
||||
default:
|
||||
return "config"
|
||||
}
|
||||
}
|
||||
|
||||
func setDefaults() {
|
||||
viper.SetDefault("server.port", "8080")
|
||||
viper.SetDefault("server.mode", "debug")
|
||||
viper.SetDefault("database.host", "localhost")
|
||||
viper.SetDefault("database.port", "3306")
|
||||
viper.SetDefault("database.charset", "utf8mb4")
|
||||
viper.SetDefault("jwt.access_token_ttl", 3600)
|
||||
viper.SetDefault("jwt.refresh_token_ttl", 604800)
|
||||
viper.SetDefault("redis.host", "localhost")
|
||||
viper.SetDefault("redis.port", "6379")
|
||||
viper.SetDefault("redis.db", 0)
|
||||
viper.SetDefault("app.name", "AI English Learning")
|
||||
viper.SetDefault("app.version", "1.0.0")
|
||||
viper.SetDefault("app.environment", "development")
|
||||
viper.SetDefault("app.log_level", "info")
|
||||
viper.SetDefault("log.level", "info")
|
||||
viper.SetDefault("log.format", "json")
|
||||
viper.SetDefault("log.output", "both")
|
||||
viper.SetDefault("log.file_path", "./logs/app.log")
|
||||
viper.SetDefault("log.max_size", 100)
|
||||
viper.SetDefault("log.max_backups", 10)
|
||||
viper.SetDefault("log.max_age", 30)
|
||||
viper.SetDefault("log.compress", true)
|
||||
}
|
||||
|
||||
func overrideFromEnv() {
|
||||
if dbPassword := os.Getenv("DB_PASSWORD"); dbPassword != "" {
|
||||
GlobalConfig.Database.Password = dbPassword
|
||||
}
|
||||
if jwtSecret := os.Getenv("JWT_SECRET"); jwtSecret != "" {
|
||||
GlobalConfig.JWT.Secret = jwtSecret
|
||||
}
|
||||
if redisPassword := os.Getenv("REDIS_PASSWORD"); redisPassword != "" {
|
||||
GlobalConfig.Redis.Password = redisPassword
|
||||
}
|
||||
}
|
||||
40
serve/config/config.prod.yaml
Normal file
40
serve/config/config.prod.yaml
Normal file
@@ -0,0 +1,40 @@
|
||||
# AI英语学习平台 - 生产环境配置
|
||||
|
||||
server:
|
||||
port: "8050"
|
||||
mode: "release" # debug, release, test
|
||||
|
||||
database:
|
||||
host: "8.149.233.36"
|
||||
port: "3306"
|
||||
user: "ai_english_learning"
|
||||
password: "7aK_H2yvokVumr84lLNDt8fDBp6P" # 必须通过环境变量 DB_PASSWORD 设置
|
||||
dbname: "ai_english_learning"
|
||||
charset: "utf8mb4"
|
||||
|
||||
jwt:
|
||||
secret: "" # 必须通过环境变量 JWT_SECRET 设置
|
||||
access_token_ttl: 7200 # 2小时
|
||||
refresh_token_ttl: 2592000 # 30天
|
||||
|
||||
redis:
|
||||
host: "localhost"
|
||||
port: "6379"
|
||||
password: "" # 建议通过环境变量 REDIS_PASSWORD 设置
|
||||
db: 0
|
||||
|
||||
app:
|
||||
name: "AI English Learning"
|
||||
version: "1.0.0"
|
||||
environment: "production"
|
||||
log_level: "info"
|
||||
|
||||
log:
|
||||
level: "debug" # debug, info, warn, error, fatal, panic
|
||||
format: "text" # json, text
|
||||
output: "both" # console, file, both
|
||||
file_path: "./logs/prod.log"
|
||||
max_size: 100 # MB
|
||||
max_backups: 5
|
||||
max_age: 7 # days
|
||||
compress: false
|
||||
40
serve/config/config.yaml
Normal file
40
serve/config/config.yaml
Normal file
@@ -0,0 +1,40 @@
|
||||
# AI英语学习平台配置文件
|
||||
|
||||
server:
|
||||
port: "8080"
|
||||
mode: "debug" # debug, release, test
|
||||
|
||||
database:
|
||||
host: "localhost"
|
||||
port: "3306"
|
||||
user: "root"
|
||||
password: "JKjk20011115" # 建议通过环境变量 DB_PASSWORD 设置
|
||||
dbname: "ai_english_learning"
|
||||
charset: "utf8mb4"
|
||||
|
||||
jwt:
|
||||
secret: "" # 建议通过环境变量 JWT_SECRET 设置
|
||||
access_token_ttl: 3600 # 1小时
|
||||
refresh_token_ttl: 604800 # 7天
|
||||
|
||||
redis:
|
||||
host: "localhost"
|
||||
port: "6379"
|
||||
password: "" # 建议通过环境变量 REDIS_PASSWORD 设置
|
||||
db: 0
|
||||
|
||||
app:
|
||||
name: "AI English Learning"
|
||||
version: "1.0.0"
|
||||
environment: "development" # development, staging, production
|
||||
log_level: "info" # debug, info, warn, error
|
||||
|
||||
log:
|
||||
level: "info" # debug, info, warn, error, fatal, panic
|
||||
format: "json" # json, text
|
||||
output: "both" # console, file, both
|
||||
file_path: "./logs/app.log"
|
||||
max_size: 100 # MB
|
||||
max_backups: 10
|
||||
max_age: 30 # days
|
||||
compress: true
|
||||
Reference in New Issue
Block a user