配置文件从consul的配置中读取,监听配置文件改变的状态
This commit is contained in:
162
consul/consul.go
162
consul/consul.go
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user