package config import ( "context" "fmt" "github.com/spf13/viper" _ "github.com/spf13/viper/remote" "github.com/zeromicro/go-zero/zrpc" "go.etcd.io/etcd/api/v3/mvccpb" clientv3 "go.etcd.io/etcd/client/v3" "log" "os" ) const ( TypeKey = "CONFIG_TYPE" // 配置文件类型 TypeEtcd = "etcd" TypeEnv = "env" Prefix = "/youtu/config/" // 配置文件前缀 EtcdAddrKey = "ETCD_ADDR" ) type Redis struct { Host string `json:"host"` Password string `json:"password"` } type AppAccount struct { AppId string `json:"appId"` Secret string `json:"secret"` Type string `json:"type"` } type Config struct { RpcServerConf zrpc.RpcServerConf Mode string Mysql string Redis []Redis } func init() { etcdAddr := "192.168.0.47:2379" envEtcdAddr := os.Getenv(EtcdAddrKey) if envEtcdAddr != "" { etcdAddr = envEtcdAddr } viper.SetDefault(EtcdAddrKey, etcdAddr) viper.SetDefault(TypeKey, TypeEtcd) } func GetConfig(c *Config, serverName string) (err error) { err = viper.AddRemoteProvider("etcd3", viper.GetString(EtcdAddrKey), Prefix+serverName+".rpc") fmt.Println(Prefix + serverName + ".rpc") if err != nil { return } viper.SetConfigType("json") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop", "env", "dotenv" err = viper.ReadRemoteConfig() if err != nil { return } // 读取公共配置并合并 serviceConfig := viper.New() err = serviceConfig.AddRemoteProvider("etcd3", viper.GetString(EtcdAddrKey), Prefix+"common.rpc") if err != nil { log.Fatalf("Failed to read service config: %v", err) return err } serviceConfig.SetConfigType("json") if err := serviceConfig.ReadRemoteConfig(); err != nil { log.Fatalf("Failed to read service config: %v", err) } err = viper.MergeConfigMap(serviceConfig.AllSettings()) if err != nil { return err } err = viper.Unmarshal(&c) if err != nil { return } c.RpcServerConf.Name = serverName + ".rpc" c.RpcServerConf.Etcd.Key = serverName + ".rpc" c.RpcServerConf.ServiceConf.Mode = c.Mode return } func SetConfig(b, serverName string) (err error) { etcdCli, err := clientv3.NewFromURL(viper.GetString(EtcdAddrKey)) if err != nil { return } _, err = etcdCli.Put(context.Background(), Prefix+serverName+".rpc", b) return } type WatchKV struct { Key string Value []byte Type mvccpb.Event_EventType } // EtcdGetOneAndWatch 获取etcd配置并监听对应的key func EtcdGetOneAndWatch(ctx context.Context, cli *clientv3.Client, key string, ch chan WatchKV) { defer close(ch) b, err := cli.Get(ctx, key, clientv3.WithPrefix()) if err != nil { return } for _, kv := range b.Kvs { ch <- WatchKV{Key: string(kv.Key), Value: kv.Value} } resCh := cli.Watch(ctx, key, clientv3.WithPrefix()) for res := range resCh { for _, event := range res.Events { ch <- WatchKV{Key: string(event.Kv.Key), Value: event.Kv.Value, Type: event.Type} } } return }