package utils import ( "crypto/md5" "encoding/hex" "fmt" "net/url" "os" "path/filepath" "sync" "time" "github.com/fsnotify/fsnotify" "github.com/spf13/viper" ) var ( localViper = viper.New() runViper = viper.New() loadOnce sync.Once nacosHost string namespace string dataId string group string currentMd5 string ) func GetConfig(key string) interface{} { return runViper.Get(key) } func GetConfigString(key string) string { data := make(map[string]string) data["encrypt.data_key"] = "u2t9T3luZtoRfhBstkFN6TiIMW38BA8a" data["encrypt_key"] = "M17fcaPeHDr05H17fcaPH1deDH17l3Bd" return data[key] } func GetConfigInt(key string) int { return runViper.GetInt(key) } func GetConfigInt64(key string) int64 { return runViper.GetInt64(key) } func GetConfigBool(key string) bool { return runViper.GetBool(key) } func InitConfig() { loadOnce.Do(func() { autoLoadLocalConfig() // 初始化尝试拉取Nacos,失败降级本地缓存 err := fetchNacosAndSaveRunToml() if err != nil { Logger.Error("初始化拉取Nacos配置失败,降级使用本地run.toml缓存", err) } // 加载配置文件(不管Nacos成功与否,一定加载本地run.toml) loadRunToml() // 启动定时后台重试协程 startFixedIntervalSync() }) } func autoLoadLocalConfig() { localViper.SetConfigName("env") localViper.SetConfigType("toml") paths := []string{ "./", "./config", } for _, p := range paths { fullPath := filepath.Join(getWorkDir(), p) if _, err := os.Stat(fullPath); err == nil { localViper.AddConfigPath(fullPath) } } err := localViper.ReadInConfig() if err != nil { Logger.Panic("找不到 env.toml") } nacosHost = localViper.GetString("rnacos.host") namespace = localViper.GetString("rnacos.namespace") dataId = localViper.GetString("rnacos.dataid") group = localViper.GetString("rnacos.group") // 修复大概率遗漏http://,curl请求会直接失败 if nacosHost != "" && nacosHost[:7] != "http://" && nacosHost[:8] != "https://" { nacosHost = "http://" + nacosHost } } func fetchNacosConfig() (string, string, error) { uri := fmt.Sprintf( "nacos/v1/cs/configs?dataId=%s&group=%s&tenant=%s", url.QueryEscape(dataId), url.QueryEscape(group), url.QueryEscape(namespace), ) body, err := Curl(nacosHost).Get(uri) if err != nil { return "", "", fmt.Errorf("curl请求nacos失败: %w", err) } hash := md5.Sum([]byte(body)) md5Str := hex.EncodeToString(hash[:]) return body, md5Str, nil } func fetchNacosAndSaveRunToml() error { body, newMd5, err := fetchNacosConfig() if err != nil { return err } // MD5一致无需更新 if currentMd5 == newMd5 { return nil } // 写入本地文件 err = os.WriteFile("run.toml", []byte(body), 0644) if err != nil { return fmt.Errorf("写入run.toml失败: %w", err) } currentMd5 = newMd5 return nil } func loadRunToml() { runViper.SetConfigFile("run.toml") if err := runViper.ReadInConfig(); err != nil { panic(fmt.Sprintf("run.toml 缺失 %s ", err)) } runViper.WatchConfig() runViper.OnConfigChange(func(e fsnotify.Event) { }) } func startFixedIntervalSync() { go func() { ticker := time.NewTicker(5 * time.Minute) defer ticker.Stop() for range ticker.C { err := fetchNacosAndSaveRunToml() if err != nil { fmt.Errorf("run.toml 缺失 %w ", err) continue } } }() } func getWorkDir() string { dir, _ := os.Getwd() return dir }