配置文件从consul的配置中读取,监听配置文件改变的状态

This commit is contained in:
2026-04-10 15:54:39 +08:00
parent 0c80c5fd8b
commit f58002f8f2
4 changed files with 175 additions and 17 deletions

View File

@@ -13,7 +13,11 @@ import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/gsel"
"github.com/gogf/gf/v2/net/gsvc"
"github.com/gogf/gf/v2/os/gcfg"
"github.com/gogf/gf/v2/os/genv"
"github.com/gogf/gf/v2/util/grand"
"github.com/hashicorp/consul/api"
"github.com/r3labs/diff/v2"
)
var (
@@ -135,7 +139,165 @@ func init() {
// 连接成功后启动健康检查和自动重连
go startHealthCheckAndReconnect()
}
loadConfigFromConsul()
}
func loadConfigFromConsul() {
ctx := context.Background()
serviceName := g.Cfg().MustGet(ctx, "server.name", "admin-go").String()
env := genv.Get("APP_ENV", "").String()
fmt.Printf("服务名称: %s, 环境变量 APP_ENV: %s\n", serviceName, env)
if env == "" {
fmt.Printf("未设置 APP_ENV 环境变量,跳过 Consul 配置加载\n")
return
}
consulData, lastIndex, err := loadEnvFromConsul(env, serviceName)
if err == nil && len(consulData) > 0 {
adapter, err := gcfg.NewAdapterContent()
if err != nil {
fmt.Printf("创建配置适配器失败: %v\n", err)
return
}
adapter.SetContent(string(consulData))
g.Cfg().SetAdapter(adapter)
fmt.Printf("已从 Consul 成功加载初始配置\n")
go watchConsulConfig(env, serviceName, lastIndex)
} else {
fmt.Printf("从 Consul 获取配置失败,使用本地配置文件\n")
}
}
func loadEnvFromConsul(env string, serviceName string) ([]byte, uint64, error) {
ctx := context.Background()
consulAddress := g.Cfg().MustGet(ctx, "consul.address", "127.0.0.1:8500").String()
fmt.Printf("Consul 地址: %s\n", consulAddress)
config := api.DefaultConfig()
config.Address = consulAddress
client, err := api.NewClient(config)
if err != nil {
fmt.Printf("创建 Consul 客户端失败: %v\n", err)
return nil, 0, err
}
consulKey := fmt.Sprintf("config/%s/%s-%s", serviceName, serviceName, env)
fmt.Printf("从 Consul 读取配置键: %s\n", consulKey)
kv := client.KV()
opts := &api.QueryOptions{
WaitIndex: 0,
WaitTime: 60 * time.Second,
}
pair, meta, err := kv.Get(consulKey, opts)
if err != nil {
fmt.Printf("从 Consul 读取配置失败: %v\n", err)
return nil, 0, err
}
if pair == nil {
fmt.Printf("Consul 中未找到配置键: %s\n", consulKey)
return nil, 0, nil
}
fmt.Printf("已从 Consul 加载配置, Index: %d\n", meta.LastIndex)
return pair.Value, meta.LastIndex, nil
}
func watchConsulConfig(env string, serviceName string, lastIndex uint64) {
ctx := context.Background()
consulAddress := g.Cfg().MustGet(ctx, "consul.address", "127.0.0.1:8500").String()
config := api.DefaultConfig()
config.Address = consulAddress
client, err := api.NewClient(config)
if err != nil {
fmt.Printf("创建 Consul 监听客户端失败: %v\n", err)
return
}
consulKey := fmt.Sprintf("config/%s/%s-%s", serviceName, serviceName, env)
for {
opts := &api.QueryOptions{
WaitIndex: lastIndex,
WaitTime: 60 * time.Second,
}
pair, meta, err := client.KV().Get(consulKey, opts)
if err != nil {
fmt.Printf("Consul 监听出错: %v, 5秒后重试...\n", err)
time.Sleep(5 * time.Second)
continue
}
if meta.LastIndex == lastIndex {
continue
}
if pair == nil {
fmt.Printf("Consul 配置被删除: %s\n", consulKey)
lastIndex = meta.LastIndex
continue
}
fmt.Printf("检测到 Consul 配置变更: %s, New Index: %d\n", consulKey, meta.LastIndex)
updateLocalConfig(pair.Value)
lastIndex = meta.LastIndex
}
}
func updateLocalConfig(content []byte) {
ctx := context.Background()
oldConfig, _ := g.Cfg().Data(ctx)
adapter, err := gcfg.NewAdapterContent()
if err != nil {
fmt.Printf("创建新配置适配器失败: %v\n", err)
return
}
adapter.SetContent(string(content))
g.Cfg().SetAdapter(adapter)
newConfig, _ := g.Cfg().Data(ctx)
changelog, err := diff.Diff(oldConfig, newConfig)
if err != nil {
fmt.Printf("配置对比失败: %v\n", err)
return
}
if len(changelog) == 0 {
fmt.Printf("配置已热更新成功(内容无实质变化)\n")
return
}
fmt.Printf("=== 检测到配置变更 (%d 项) ===\n", len(changelog))
for _, change := range changelog {
switch change.Type {
case "create":
fmt.Printf("[+] 新增: %s = %v\n", change.Path, change.To)
case "update":
fmt.Printf("[~] 修改: %s: %v -> %v\n", change.Path, change.From, change.To)
case "delete":
fmt.Printf("[-] 删除: %s (原值: %v)\n", change.Path, change.From)
}
}
fmt.Printf("=================================\n")
}
func getLocalIP() (string, error) {
// 获取本机所有网络接口
addrs, err := net.InterfaceAddrs()