配置中心
配置中心是集中管理配置信息的组件,优雅的解决了配置的动态变更、权限管理、持久化、运维成本等问题。
1. 创建配置
- 下载etcd GUI客户端:
https://tzfun.github.io/etcd-workbench/
- 创建租约
- 创建基于租约的key-value存储,将配置写入,并记录key
2. 实现配置中心
func PullConfig() Config {
ss := subscriber.MustNewEtcdSubscriber(subscriber.EtcdConf{
Hosts: []string{"localhost:2379"}, // etcd 地址
Key: "user-api-test", // 配置key
})
// 创建 configurator
cc := configurator.MustNewConfigCenter[Config](configurator.Config{
Type: "yaml", // 配置值类型:json,yaml,toml
}, ss)
// 获取配置
// 注意: 配置如果发生变更,调用的结果永远获取到最新的配置
v, err := cc.GetConfig()
if err != nil {
panic(err)
}
cc.AddListener(func() {
v, err := cc.GetConfig()
if err != nil {
panic(err)
}
//这个地方要写 触发配置变化后 需要处理的操作
println("config changed:", v.Name)
})
// 如果想监听配置变化,可以添加 listener
return v
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
3. 自定义配置中间件
go-zero官方支持etcd,如果不想使用etcd,比如想要使用consul,我们可以如下做:
# go get github.com/hashicorp/consul/api
# go get github.com/spf13/viper
1
2
2
func PullConsulConfig() Config {
ss := NewConsulSubscriber("http://localhost:8500", "config/test/user-api")
// 创建 configurator
cc := configurator.MustNewConfigCenter[Config](configurator.Config{
Type: "yaml", // 配置值类型:json,yaml,toml
}, ss)
// 获取配置
// 注意: 配置如果发生变更,调用的结果永远获取到最新的配置
v, err := cc.GetConfig()
if err != nil {
panic(err)
}
cc.AddListener(func() {
v, err := cc.GetConfig()
if err != nil {
panic(err)
}
//这个地方要写 触发配置变化后 需要处理的操作
println("config changed:", v.Name)
})
// 如果想监听配置变化,可以添加 listener
return v
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package config
import (
"bytes"
"encoding/json"
consulApi "github.com/hashicorp/consul/api"
"github.com/spf13/viper"
"github.com/zeromicro/go-zero/core/configcenter/subscriber"
"sync"
)
type ConsulSubscriber struct {
listeners []func()
lock sync.Mutex
consulCli *consulApi.Client
Path string
}
func NewConsulSubscriber(address, path string) subscriber.Subscriber {
config := &consulApi.Config{
Address: address,
}
client, err := consulApi.NewClient(config)
if err != nil {
panic(err)
}
return &ConsulSubscriber{
consulCli: client,
Path: path,
}
}
func (s *ConsulSubscriber) AddListener(listener func()) error {
s.lock.Lock()
defer s.lock.Unlock()
s.listeners = append(s.listeners, listener)
return nil
}
func (s *ConsulSubscriber) Value() (string, error) {
defaultConfig := viper.New()
defaultConfig.SetConfigType("yaml")
kvPair, _, err := s.consulCli.KV().Get(s.Path, nil)
if err != nil {
panic(err)
}
err = defaultConfig.ReadConfig(bytes.NewBuffer(kvPair.Value))
if err != nil {
panic(err)
}
settings := defaultConfig.AllSettings()
marshal, _ := json.Marshal(settings)
return string(marshal), nil
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
consul:
image: hashicorp/consul:1.18
ports:
- "8500:8500"
volumes:
- ./volume/consul/data:/consul/data
- ./volume/consul/consul.d/:/consul/config:rw
command: >
consul agent -server
-bootstrap-expect=1
-ui
-client=0.0.0.0
-data-dir=/consul/data
--config-dir=/consul/config
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14