func (d *EtcdV3Discovery) GetServices() []*KVPair {
	d.pairsLock.RLock()
	defer d.pairsLock.RUnlock()
	return d.pairs
}
GetServices returns the servers
package client
import (
	"strings"
	"sync"
	"time"
	"github.com/docker/libkv"
	"github.com/docker/libkv/store"
	etcd "github.com/smallnest/libkv-etcdv3-store"
	"github.com/kudoochui/kudos/rpcx/log"
)
func init() {
	etcd.Register()
}
type EtcdV3Discovery struct {
	basePath string
	kv       store.Store
	pairs    []*KVPair
	pairsLock 	 sync.RWMutex
	chans    []chan []*KVPair
	mu       sync.Mutex
	RetriesAfterWatchFailed int
	filter ServiceDiscoveryFilter
	stopCh chan struct{}
}
func NewEtcdV3Discovery(basePath string, servicePath string, etcdAddr []string, options *store.Config) (ServiceDiscovery, error) {
	kv, err := libkv.NewStore(etcd.ETCDV3, etcdAddr, options)
	if err != nil {
		log.Infof("cannot create store: %v", err)
		panic(err)
	}
	return NewEtcdV3DiscoveryStore(basePath+"/"+servicePath, kv)
}
func NewEtcdV3DiscoveryStore(basePath string, kv store.Store) (ServiceDiscovery, error) {
	if len(basePath) > 1 && strings.HasSuffix(basePath, "/") {
		basePath = basePath[:len(basePath)-1]
	}
	d := &EtcdV3Discovery{basePath: basePath, kv: kv}
	d.stopCh = make(chan struct{})
	ps, err := kv.List(basePath)
	if err != nil {
		log.Errorf("cannot get services of from registry: %v, err: %v", basePath, err)
		panic(err)
	}
	pairs := make([]*KVPair, 0, len(ps))
	var prefix string
	for _, p := range ps {
		if prefix == "" {
			if strings.HasPrefix(p.Key, "/") {
				if strings.HasPrefix(d.basePath, "/") {
					prefix = d.basePath + "/"
				} else {
					prefix = "/" + d.basePath + "/"
				}
			} else {
				if strings.HasPrefix(d.basePath, "/") {
					prefix = d.basePath[1:] + "/"
				} else {
					prefix = d.basePath + "/"
				}
			}
		}
		if p.Key == prefix[:len(prefix)-1] {
			continue
		}
		k := strings.TrimPrefix(p.Key, prefix)
		pair := &KVPair{Key: k, Value: string(p.Value)}
		if d.filter != nil && !d.filter(pair) {
			continue
		}
		pairs = append(pairs, pair)
	}
	d.pairs = pairs
	d.RetriesAfterWatchFailed = -1
	go d.watch()
	return d, nil
}
func NewEtcdV3DiscoveryTemplate(basePath string, etcdAddr []string, options *store.Config) ServiceDiscovery {
	if len(basePath) > 1 && strings.HasSuffix(basePath, "/") {
		basePath = basePath[:len(basePath)-1]
	}
	kv, err := libkv.NewStore(etcd.ETCDV3, etcdAddr, options)
	if err != nil {
		log.Infof("cannot create store: %v", err)
		panic(err)
	}
	return &EtcdV3Discovery{basePath: basePath, kv: kv}
}
func (d *EtcdV3Discovery) Clone(servicePath string) (ServiceDiscovery, error) {
	return NewEtcdV3DiscoveryStore(d.basePath+"/"+servicePath, d.kv)
}
func (d *EtcdV3Discovery) SetFilter(filter ServiceDiscoveryFilter) {
	d.filter = filter
}