Files
lone-services/utils/config.go
T
2026-08-05 17:37:32 +08:00

153 lines
3.2 KiB
Go

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 { return runViper.GetString(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
}