You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
|
|
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
|
|
|
|
|
}
|