mirror of
https://github.com/zeromicro/go-zero.git
synced 2026-05-10 16:30:01 +08:00
feat: added configuration center function (#3035)
Co-authored-by: aiden.ma <Aiden.ma@yijinin.com>
This commit is contained in:
@@ -10,13 +10,14 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
|
||||
clientv3 "go.etcd.io/etcd/client/v3"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/contextx"
|
||||
"github.com/zeromicro/go-zero/core/lang"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"github.com/zeromicro/go-zero/core/syncx"
|
||||
"github.com/zeromicro/go-zero/core/threading"
|
||||
"go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
|
||||
clientv3 "go.etcd.io/etcd/client/v3"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -45,7 +46,7 @@ func (r *Registry) GetConn(endpoints []string) (EtcdClient, error) {
|
||||
}
|
||||
|
||||
// Monitor monitors the key on given etcd endpoints, notify with the given UpdateListener.
|
||||
func (r *Registry) Monitor(endpoints []string, key string, l UpdateListener) error {
|
||||
func (r *Registry) Monitor(endpoints []string, key string, l UpdateListener, disablePrefix bool) error {
|
||||
c, exists := r.getCluster(endpoints)
|
||||
// if exists, the existing values should be updated to the listener.
|
||||
if exists {
|
||||
@@ -55,7 +56,7 @@ func (r *Registry) Monitor(endpoints []string, key string, l UpdateListener) err
|
||||
}
|
||||
}
|
||||
|
||||
return c.monitor(key, l)
|
||||
return c.monitor(key, l, disablePrefix)
|
||||
}
|
||||
|
||||
func (r *Registry) getCluster(endpoints []string) (c *cluster, exists bool) {
|
||||
@@ -79,13 +80,14 @@ func (r *Registry) getCluster(endpoints []string) (c *cluster, exists bool) {
|
||||
}
|
||||
|
||||
type cluster struct {
|
||||
endpoints []string
|
||||
key string
|
||||
values map[string]map[string]string
|
||||
listeners map[string][]UpdateListener
|
||||
watchGroup *threading.RoutineGroup
|
||||
done chan lang.PlaceholderType
|
||||
lock sync.RWMutex
|
||||
endpoints []string
|
||||
key string
|
||||
values map[string]map[string]string
|
||||
listeners map[string][]UpdateListener
|
||||
watchGroup *threading.RoutineGroup
|
||||
done chan lang.PlaceholderType
|
||||
lock sync.RWMutex
|
||||
disablePrefix bool
|
||||
}
|
||||
|
||||
func newCluster(endpoints []string) *cluster {
|
||||
@@ -224,7 +226,12 @@ func (c *cluster) load(cli EtcdClient, key string) int64 {
|
||||
for {
|
||||
var err error
|
||||
ctx, cancel := context.WithTimeout(c.context(cli), RequestTimeout)
|
||||
resp, err = cli.Get(ctx, makeKeyPrefix(key), clientv3.WithPrefix())
|
||||
if c.disablePrefix {
|
||||
resp, err = cli.Get(ctx, key)
|
||||
} else {
|
||||
resp, err = cli.Get(ctx, makeKeyPrefix(key), clientv3.WithPrefix())
|
||||
}
|
||||
|
||||
cancel()
|
||||
if err == nil {
|
||||
break
|
||||
@@ -247,9 +254,10 @@ func (c *cluster) load(cli EtcdClient, key string) int64 {
|
||||
return resp.Header.Revision
|
||||
}
|
||||
|
||||
func (c *cluster) monitor(key string, l UpdateListener) error {
|
||||
func (c *cluster) monitor(key string, l UpdateListener, disablePrefix bool) error {
|
||||
c.lock.Lock()
|
||||
c.listeners[key] = append(c.listeners[key], l)
|
||||
c.disablePrefix = disablePrefix
|
||||
c.lock.Unlock()
|
||||
|
||||
cli, err := c.getClient()
|
||||
@@ -315,14 +323,20 @@ func (c *cluster) watch(cli EtcdClient, key string, rev int64) {
|
||||
}
|
||||
|
||||
func (c *cluster) watchStream(cli EtcdClient, key string, rev int64) error {
|
||||
var rch clientv3.WatchChan
|
||||
if rev != 0 {
|
||||
rch = cli.Watch(clientv3.WithRequireLeader(c.context(cli)), makeKeyPrefix(key),
|
||||
clientv3.WithPrefix(), clientv3.WithRev(rev+1))
|
||||
} else {
|
||||
rch = cli.Watch(clientv3.WithRequireLeader(c.context(cli)), makeKeyPrefix(key),
|
||||
clientv3.WithPrefix())
|
||||
var (
|
||||
rch clientv3.WatchChan
|
||||
ops []clientv3.OpOption
|
||||
watchKey = key
|
||||
)
|
||||
if !c.disablePrefix {
|
||||
watchKey = makeKeyPrefix(key)
|
||||
ops = append(ops, clientv3.WithPrefix())
|
||||
}
|
||||
if rev != 0 {
|
||||
ops = append(ops, clientv3.WithRev(rev+1))
|
||||
}
|
||||
|
||||
rch = cli.Watch(clientv3.WithRequireLeader(c.context(cli)), watchKey, ops...)
|
||||
|
||||
for {
|
||||
select {
|
||||
|
||||
@@ -289,7 +289,7 @@ func TestRegistry_Monitor(t *testing.T) {
|
||||
},
|
||||
}
|
||||
GetRegistry().lock.Unlock()
|
||||
assert.Error(t, GetRegistry().Monitor(endpoints, "foo", new(mockListener)))
|
||||
assert.Error(t, GetRegistry().Monitor(endpoints, "foo", new(mockListener), false))
|
||||
}
|
||||
|
||||
type mockListener struct {
|
||||
|
||||
@@ -15,9 +15,10 @@ type (
|
||||
|
||||
// A Subscriber is used to subscribe the given key on an etcd cluster.
|
||||
Subscriber struct {
|
||||
endpoints []string
|
||||
exclusive bool
|
||||
items *container
|
||||
endpoints []string
|
||||
exclusive bool
|
||||
disablePrefix bool
|
||||
items *container
|
||||
}
|
||||
)
|
||||
|
||||
@@ -34,7 +35,7 @@ func NewSubscriber(endpoints []string, key string, opts ...SubOption) (*Subscrib
|
||||
}
|
||||
sub.items = newContainer(sub.exclusive)
|
||||
|
||||
if err := internal.GetRegistry().Monitor(endpoints, key, sub.items); err != nil {
|
||||
if err := internal.GetRegistry().Monitor(endpoints, key, sub.items, sub.disablePrefix); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -59,6 +60,13 @@ func Exclusive() SubOption {
|
||||
}
|
||||
}
|
||||
|
||||
// WithDisablePrefix turn off querying using key prefixes.
|
||||
func WithDisablePrefix() SubOption {
|
||||
return func(sub *Subscriber) {
|
||||
sub.disablePrefix = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithSubEtcdAccount provides the etcd username/password.
|
||||
func WithSubEtcdAccount(user, pass string) SubOption {
|
||||
return func(sub *Subscriber) {
|
||||
|
||||
Reference in New Issue
Block a user