package discovery import ( "context" "errors" clientv3 "go.etcd.io/etcd/client/v3" "math/rand" "time" ) type Discovery interface { // 获取某个服务器的一个实例地址 GetServiceAddr(serviceName string) (string, error) // 监控某个服务的地址变化 WatchService(serviceName string) error } type DiscoveryEtcd struct { cli *clientv3.Client } // 实例化的方法 func NewDiscoveryEtcd(endpoints []string) (*DiscoveryEtcd, error) { // 一,没有etcd的地址,直接返回 if len(endpoints) == 0 { return nil, errors.New("endpoints is empty") } // 二,连接etcd cli, err := clientv3.New(clientv3.Config{ Endpoints: endpoints, DialTimeout: 3 * time.Second, }) if err != nil { return nil, err } // 实例化 de := &DiscoveryEtcd{cli: cli} return de, nil } func (de *DiscoveryEtcd) GetServiceAddr(serviceName string) (string, error) { // 执行 Get 操作 getResp, err := de.cli.Get(context.Background(), serviceName, clientv3.WithPrefix()) if err != nil { return "", err } // 处理查询到的结果 if len(getResp.Kvs) == 0 { return "", errors.New("service not found") } // 采用随机的LB,LoadBalance 算法 randIndex := rand.Intn(len(getResp.Kvs)) // [0, n) addr := string(getResp.Kvs[randIndex].Value) // 返回地址 return addr, nil }