Skip to content

Commit 25566e3

Browse files
committed
refactor: 重构了一下config
1 parent 7de9c47 commit 25566e3

12 files changed

Lines changed: 383 additions & 381 deletions

File tree

example/config/config.go

Lines changed: 34 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ package main
22

33
import (
44
"log"
5-
"time"
65

7-
"github.com/muxi-Infra/muxi-micro/pkg/config"
6+
"github.com/muxi-Infra/muxi-micro/pkg/config/local"
7+
"github.com/muxi-Infra/muxi-micro/pkg/config/nacos"
88
)
99

1010
type DatabaseConfig struct {
@@ -29,74 +29,54 @@ type Config struct {
2929
}
3030

3131
func Local() {
32-
// 选择本地就newloaclconfig
33-
cfg, err := config.NewLocalConfig(&Config{}, "config.yaml")
34-
if err != nil { //结构体传入时不用指针就报错
35-
log.Fatal(err)
36-
}
37-
// 加载配置
38-
err = cfg.LoadData()
39-
// 检查是否有错误
32+
cfg, err := local.LoadLocalConfig[Config]("./example.yaml", local.WithWatchChanSize(10))
4033
if err != nil {
41-
log.Fatalf("加载配置失败: %v", err)
34+
log.Fatal(err)
4235
}
43-
// 输出时需要类型断言
44-
log.Println(cfg.GetData().(*Config).Database.MySQL.Host)
36+
defer cfg.Close()
4537

46-
//ch用于监听热更新信号
47-
ch := cfg.WatchData()
48-
49-
go func() {
50-
for err := range ch {
51-
// 用户自定义热更新后的操作
52-
if err == nil {
53-
log.Println(cfg.GetData().(*Config).Database.MySQL.Host)
54-
} else {
55-
log.Println("err: ", err)
56-
}
57-
}
58-
}()
38+
data := cfg.GetData()
39+
log.Printf("MySQL Host: %s", data.Database.MySQL.Host)
40+
log.Printf("Redis DB: %s", data.Database.Redis.DB)
5941

60-
time.Sleep(20 * time.Second)
61-
// 其实local的关闭不会报错,nacos才会
62-
err = cfg.Close()
63-
if err != nil {
64-
log.Println(err)
42+
ch := cfg.WatchData()
43+
for range ch {
44+
updatedData := cfg.GetData()
45+
log.Printf("MySQL Host: %s", updatedData.Database.MySQL.Host)
6546
}
6647
}
6748

6849
func Nacos() {
69-
// 预先配置
70-
c := config.NewClientConfig("public", "nacos", "nacos", 5000)
71-
s := config.NewServerConfig([]string{"localhost"}, []uint64{8848})
72-
// GET
73-
cfg2, err := config.NewNacosConfig("key3", "1GRUOP", "", c, s)
50+
clientAddr := []nacos.ClientAddr{
51+
{Ip: "localhost", Port: 8848},
52+
}
53+
client, err := nacos.NewNacosClient(
54+
"new",
55+
"nacos",
56+
"nacos",
57+
"",
58+
1000,
59+
clientAddr,
60+
)
7461
if err != nil {
7562
log.Fatal(err)
7663
}
77-
err = cfg2.LoadData()
64+
defer client.CloseClient()
65+
66+
cfg, err := nacos.LoadNacosConfig[Config](client, "test", "test")
7867
if err != nil {
7968
log.Fatal(err)
8069
}
81-
log.Println(cfg2.GetData())
70+
defer cfg.Close()
8271

83-
// 监听
84-
ch := cfg2.WatchData()
85-
go func() {
86-
for err := range ch {
87-
// 用户自定义热更新后的操作
88-
if err != nil {
89-
log.Println(err)
90-
} else {
91-
log.Println("配置已更新:", cfg2.GetData())
92-
}
93-
}
94-
}()
72+
data := cfg.GetData()
73+
log.Printf("MySQL Host: %s", data.Database.MySQL.Host)
74+
log.Printf("Redis DB: %s", data.Database.Redis.DB)
9575

96-
time.Sleep(10 * time.Second)
97-
err = cfg2.Close()
98-
if err != nil {
99-
log.Println(err)
76+
ch := cfg.WatchData()
77+
for range ch {
78+
updatedData := cfg.GetData()
79+
log.Printf("MySQL Host: %s", updatedData.Database.MySQL.Host)
10080
}
10181
}
10282

example/config/example.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
database:
2+
mysql:
3+
host: "localhost"
4+
port: "3306"
5+
username: "root"
6+
password: "password"
7+
redis:
8+
host: "localhost"
9+
port: "6379"
10+
username: "root"
11+
password: "password"
12+
db: "0"

example/transport/grpc/client/main.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
package micro
22

33
import (
4+
pb "github.com/muxi-Infra/muxi-micro/example/transport/grpc/proto"
45
"github.com/muxi-Infra/muxi-micro/pkg/transport/grpc"
56
"github.com/muxi-Infra/muxi-micro/pkg/transport/grpc/discovery/etcd"
6-
7-
pb "github.com/muxi-Infra/muxi-micro/tool/micro/proto"
87
)
98

109
// 和proto一起生成的客户端模板的大致形式

pkg/config/config.go

Lines changed: 4 additions & 232 deletions
Original file line numberDiff line numberDiff line change
@@ -1,235 +1,7 @@
11
package config
22

3-
import (
4-
"errors"
5-
"path/filepath"
6-
"reflect"
7-
"sync"
8-
"time"
9-
10-
"github.com/fsnotify/fsnotify"
11-
"github.com/nacos-group/nacos-sdk-go/v2/clients"
12-
"github.com/nacos-group/nacos-sdk-go/v2/clients/config_client"
13-
"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
14-
"github.com/nacos-group/nacos-sdk-go/v2/vo"
15-
"github.com/spf13/viper"
16-
)
17-
18-
type ConfigManager interface {
19-
GetData() interface{} // 获取配置数据
20-
LoadData() error // 先加载再获取数据
21-
WatchData() <-chan error //热更新
22-
Close() error //关闭
23-
}
24-
25-
// yaml和json部分
26-
type LocalConfig struct {
27-
Viper *viper.Viper
28-
Lastupdate time.Time
29-
Data interface{} // 传入的配置结构体指针
30-
Path string // 配置文件路径
31-
Check int // 0表示监听未开启,1表示已开启,2表示停止监听,不会再触发热更新操作
32-
mu sync.Mutex
33-
ch chan error //传递更新信号或错误的管道
34-
}
35-
36-
// c需传入结构体指针,返回接口类型
37-
func NewLocalConfig(c interface{}, path string) (ConfigManager, error) {
38-
if reflect.ValueOf(c).Kind() != reflect.Ptr {
39-
return nil, errors.New("config struct must be a pointer")
40-
}
41-
return &LocalConfig{
42-
Viper: viper.New(),
43-
Data: c,
44-
Lastupdate: time.Now(),
45-
Path: path,
46-
Check: 0,
47-
mu: sync.Mutex{},
48-
ch: make(chan error),
49-
}, nil
50-
}
51-
52-
func (l *LocalConfig) GetData() interface{} {
53-
return l.Data
54-
}
55-
56-
func (l *LocalConfig) LoadData() error {
57-
l.Viper.SetConfigFile(l.Path)
58-
59-
// 检查扩展名(支持yaml, json),如果不是则报错
60-
ext := filepath.Ext(l.Path)
61-
switch ext {
62-
case ".yaml", ".yml":
63-
l.Viper.SetConfigType("yaml")
64-
case ".json":
65-
l.Viper.SetConfigType("json")
66-
default:
67-
return errors.New("only .yaml, .yml, or .json are supported")
68-
}
69-
70-
// 读取配置文件
71-
err := loadData(l)
72-
return err
73-
}
74-
75-
// 传回的通道会在配置文件发生变化时发送信号
76-
func (l *LocalConfig) WatchData() <-chan error {
77-
// 如果已经监听过就退出,防止开多个协程监听,不将错误传入管道了避免与热更新的错误混淆
78-
if l.Check == 1 {
79-
return nil
80-
}
81-
l.Check = 1
82-
83-
l.Viper.OnConfigChange(func(e fsnotify.Event) {
84-
l.mu.Lock()
85-
defer l.mu.Unlock()
86-
// 停止监听就退出
87-
if l.Check == 2 {
88-
return
89-
}
90-
// 不知道为什么会连着调用两次,所以加个时间限制
91-
if time.Since(l.Lastupdate) < 1*time.Second {
92-
return
93-
}
94-
err := loadData(l)
95-
if err != nil {
96-
// 热更新时出错
97-
l.ch <- err
98-
return
99-
}
100-
// 发送信号通知配置已更新
101-
l.ch <- nil
102-
})
103-
l.Viper.WatchConfig()
104-
105-
return l.ch
106-
}
107-
108-
func (l *LocalConfig) Close() error {
109-
close(l.ch)
110-
// 停止监听标志
111-
l.Check = 2
112-
// 感觉没有错误但得和nacos的一致
113-
return nil
3+
type ConfigManager[T any] interface {
4+
GetData() *T // 获取配置数据
5+
WatchData() <-chan struct{} // 热更新, 只负责更新数据, 不负责更新后的操作
6+
Close() error // 关闭
1147
}
115-
116-
func loadData(l *LocalConfig) error {
117-
if err := l.Viper.ReadInConfig(); err != nil {
118-
return err
119-
}
120-
121-
if err := l.Viper.Unmarshal(l.Data); err != nil {
122-
return err
123-
}
124-
125-
l.Lastupdate = time.Now()
126-
return nil
127-
}
128-
129-
// Nacos部分
130-
// 定义查询结构体
131-
type NacosConfig struct {
132-
DataId string // 配置key
133-
Group string // 配置组
134-
Data string // 配置value,获取值时也在这里获取
135-
Client config_client.IConfigClient // Nacos客户端
136-
Check int
137-
ch chan error
138-
mu sync.Mutex
139-
}
140-
141-
func NewClientConfig(namespace, username, password string, time uint64) *constant.ClientConfig {
142-
return &constant.ClientConfig{
143-
NamespaceId: namespace,
144-
TimeoutMs: time,
145-
Username: username,
146-
Password: password,
147-
}
148-
}
149-
150-
func NewServerConfig(ip []string, port []uint64) []constant.ServerConfig {
151-
serverConfigs := make([]constant.ServerConfig, 0, len(ip))
152-
for i := 0; i < len(ip); i++ {
153-
serverConfigs = append(serverConfigs, constant.ServerConfig{
154-
IpAddr: ip[i],
155-
Port: port[i],
156-
})
157-
}
158-
return serverConfigs
159-
}
160-
161-
// 创建nacos客户端
162-
func NewNacos(clientConfig *constant.ClientConfig, serverConfigs []constant.ServerConfig) (config_client.IConfigClient, error) {
163-
client, err := clients.NewConfigClient(vo.NacosClientParam{
164-
ClientConfig: clientConfig,
165-
ServerConfigs: serverConfigs,
166-
})
167-
if err != nil {
168-
return nil, err
169-
}
170-
return client, nil
171-
}
172-
173-
// 返回接口类型
174-
func NewNacosConfig(dataId, group, content string, clientconfig *constant.ClientConfig, serverconfig []constant.ServerConfig) (ConfigManager, error) {
175-
client, err := NewNacos(clientconfig, serverconfig)
176-
if err != nil {
177-
return nil, err
178-
}
179-
return &NacosConfig{
180-
DataId: dataId,
181-
Group: group,
182-
Data: content,
183-
Client: client,
184-
Check: 0,
185-
ch: make(chan error),
186-
mu: sync.Mutex{},
187-
}, nil
188-
}
189-
190-
func (p *NacosConfig) GetData() interface{} {
191-
return p.Data
192-
}
193-
194-
func (p *NacosConfig) LoadData() error {
195-
content, err := p.Client.GetConfig(vo.ConfigParam{
196-
DataId: p.DataId,
197-
Group: p.Group,
198-
})
199-
if err != nil {
200-
return err
201-
}
202-
p.Data = content
203-
return nil
204-
}
205-
206-
func (p *NacosConfig) WatchData() <-chan error {
207-
if p.Check == 1 {
208-
return nil
209-
}
210-
p.Check = 1
211-
err := p.Client.ListenConfig(vo.ConfigParam{
212-
DataId: p.DataId,
213-
Group: p.Group,
214-
OnChange: func(namespace, group, dataId, data string) {
215-
p.mu.Lock()
216-
defer p.mu.Unlock()
217-
p.Data = data
218-
p.ch <- nil
219-
},
220-
})
221-
if err != nil {
222-
p.ch <- err
223-
}
224-
return p.ch
225-
}
226-
227-
func (p *NacosConfig) Close() error {
228-
// nacos提供了专门关闭方法
229-
cancelParam := vo.ConfigParam{
230-
DataId: p.DataId,
231-
Group: p.Group,
232-
}
233-
p.Check = 0
234-
return p.Client.CancelListenConfig(cancelParam)
235-
}

0 commit comments

Comments
 (0)