85 lines
1.8 KiB
Go
85 lines
1.8 KiB
Go
package resolver
|
|
|
|
import (
|
|
"context"
|
|
"git.hlsq.asia/mmorpg/service-common/db/etcd"
|
|
"git.hlsq.asia/mmorpg/service-common/discover/common"
|
|
"git.hlsq.asia/mmorpg/service-common/log"
|
|
"go.etcd.io/etcd/client/v3"
|
|
"google.golang.org/grpc/resolver"
|
|
"strings"
|
|
)
|
|
|
|
const etcdSchema = "etcd"
|
|
|
|
func init() {
|
|
resolver.Register(&etcdBuilder{})
|
|
}
|
|
|
|
type etcdBuilder struct{}
|
|
|
|
func (*etcdBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
|
|
serviceName := strings.TrimPrefix(target.URL.Path, "/")
|
|
r := &etcdResolver{
|
|
serviceName: serviceName,
|
|
cc: cc,
|
|
}
|
|
r.start()
|
|
return r, nil
|
|
}
|
|
|
|
func (*etcdBuilder) Scheme() string { return etcdSchema }
|
|
|
|
type etcdResolver struct {
|
|
serviceName string
|
|
cc resolver.ClientConn
|
|
ctx context.Context
|
|
cancel context.CancelFunc
|
|
}
|
|
|
|
func (r *etcdResolver) start() {
|
|
r.ctx, r.cancel = context.WithCancel(context.Background())
|
|
r.update()
|
|
go r.watch()
|
|
}
|
|
|
|
func (r *etcdResolver) getPrefix() string {
|
|
return common.KeyDiscoverService + "/" + r.serviceName
|
|
}
|
|
|
|
func (r *etcdResolver) update() {
|
|
resp, err := etcd.GetClient().Get(r.getPrefix(), clientv3.WithPrefix())
|
|
if err != nil {
|
|
log.Errorf("etcd resolver get error: %v", err)
|
|
return
|
|
}
|
|
|
|
var addrArray []resolver.Address
|
|
for _, kv := range resp.Kvs {
|
|
addr := string(kv.Value)
|
|
if addr != "" {
|
|
addrArray = append(addrArray, resolver.Address{Addr: addr})
|
|
}
|
|
}
|
|
|
|
_ = r.cc.UpdateState(resolver.State{Addresses: addrArray})
|
|
}
|
|
|
|
func (r *etcdResolver) watch() {
|
|
watchCh := etcd.GetClient().Watch(r.getPrefix(), clientv3.WithPrefix())
|
|
for w := range watchCh {
|
|
if w.Err() != nil {
|
|
continue
|
|
}
|
|
r.update()
|
|
}
|
|
}
|
|
|
|
func (r *etcdResolver) ResolveNow(resolver.ResolveNowOptions) {
|
|
r.update()
|
|
}
|
|
|
|
func (r *etcdResolver) Close() {
|
|
r.cancel()
|
|
}
|