gRPC服务发现&负载均衡的watcher必须暂停一秒,不然会出现code = Unavailable desc = there is no address available错误

gRPC服务发现&负载均衡的watcher必须暂停一秒,不然会出现code = Unavailable desc = there is no address available错误.以下是watcher代码,网上copy的.地址是:https://segmentfault.com/a/1190000008672912
请教一下,发生错误的原因是什么?
谢谢.


package etcdv3

import (
"fmt"
etcd3 "github.com/coreos/etcd/clientv3"
"golang.org/x/net/context"
"google.golang.org/grpc/naming"
"github.com/coreos/etcd/mvcc/mvccpb"
)

// watcher is the implementaion of grpc.naming.Watcher
type watcher struct {
re *resolver // re: Etcd Resolver
client etcd3.Client
isInitialized bool
}

// Close do nothing
func (w *watcher) Close() {
}

// Next to return the updates
func (w *watcher) Next() ([]*naming.Update, error) {
// prefix is the etcd prefix/value to watch
prefix := fmt.Sprintf("/%s/%s/", Prefix, w.re.serviceName)

// check if is initialized
if !w.isInitialized {
// query addresses from etcd
resp, err := w.client.Get(context.Background(), prefix, etcd3.WithPrefix())
w.isInitialized = true
if err == nil {
addrs := extractAddrs(resp)
//if not empty, return the updates or watcher new dir
if l := len(addrs); l != 0 {
updates := make([]*naming.Update, l)
for i := range addrs {
updates[i] = &naming.Update{Op: naming.Add, Addr: addrs[i]}
}
return updates, nil
}
}
}

// generate etcd Watcher
rch := w.client.Watch(context.Background(), prefix, etcd3.WithPrefix())
for wresp := range rch {
for _, ev := range wresp.Events {
switch ev.Type {
case mvccpb.PUT:
return []*naming.Update{{Op: naming.Add, Addr: string(ev.Kv.Value)}}, nil
case mvccpb.DELETE:
return []*naming.Update{{Op: naming.Delete, Addr: string(ev.Kv.Value)}}, nil
}
}
}
return nil, nil
}

func extractAddrs(resp *etcd3.GetResponse) []string {
addrs := []string{}

if resp == nil || resp.Kvs == nil {
return addrs
}

for i := range resp.Kvs {
if v := resp.Kvs[i].Value; v != nil {
addrs = append(addrs, string(v))
}
}

return addrs
}
已邀请:

トトロ

赞同来自: elvin5

猜测是异步的原因,试试Dial的时候加上WithBlock?
etcd官方有一个包提供Resolver

stirlingx - https://github.com/liyue201

赞同来自:

yacc2007

赞同来自:

Dial的时候加上WithBlock应该就可以了,异步的问题

要回复问题请先登录注册