126 lines
2.9 KiB
Go

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
}