etcd服务负载均衡

负载均衡接口


var (
	ErrNotHaveNodes = errors.New("not have node")
)

type LoadBalance interface {
	Name() string
	Select(ctx context.Context, nodes []*registry.Node) (node *registry.Node, err error)
}

Name接口返回负载均衡的名称

Select接口返回节点node信息,

// 服务节点的抽象
type Node struct {
	Id     string `json:"id"`
	IP     string `json:"ip"`
	Port   int    `json:"port"`
	Weight int    `json:"weight"`
}

1、随机

ype RandomBalance struct {
}

func (r *RandomBalance) Name() string {
	return "random"
}

func (r *RandomBalance) Select(ctx context.Context, nodes []*registry.Node) (node *registry.Node, err error) {

	if len(nodes) == 0 {
		err = ErrNotHaveNodes
		return
	}

    index := rand.Intn(len(nodes))
	node = nodes[index]
	return
}

2、轮训

type RoundRobinBalance struct {
	index int
}

func (r *RoundRobinBalance) Name() string {
	return "roundrobin"
}

func (r *RoundRobinBalance) Select(ctx context.Context, nodes []*registry.Node) (node *registry.Node, err error) {

	if len(nodes) == 0 {
		err = ErrNotHaveNodes
		return
	}

	r.index = (r.index + 1) % len(nodes)
	node = nodes[r.index]

	return
}

3、权重

关于权重,

type WeightBalance struct {
}

func (r *WeightBalance) Name() string {
	return "weight"
}

func (r *WeightBalance) Select(ctx context.Context, nodes []*registry.Node) (node *registry.Node, err error) {

	if len(nodes) == 0 {
		err = ErrNotHaveNodes
		return
	}

	var totalWeight int
	for _, val := range nodes {
		if val.Weight == 0 {
			val.Weight = DefaultNodeWeight
		}
		totalWeight += val.Weight
	}

	curWeight := rand.Intn(totalWeight)
	curIndex := -1
	for index, node := range nodes {
		curWeight -= node.Weight
		if curWeight < 0 {
			curIndex = index
			break
		}
	}

	if curIndex == -1 {
		err = ErrNotHaveNodes
		return
	}

	node = nodes[curIndex]
	return
}

测试 关于权重, 比如有3个节点

权重是50 + 100 + 150   =  300 

假如curWeight = 270    

270 - 50 = 220      220 - 100  = 120  120 - 150 = -30    节点3

180 - 50 = 130     130 -  100 = 30    30 - 150 = -120   节点3

150   以上都是节点3    50 以上都是节点 2        50 一下是 节点1  所以  节点3选中的概率是 50 %

func TestSelect(t *testing.T) {

	balance := &RandomBalance{}
	var weights = [3]int{50, 100, 150}
	var nodes []*registry.Node
	for i := 0; i < 4; i++ {
		node := &registry.Node{
			IP:     fmt.Sprintf("127.0.0.%d", i),
			Port:   8080,
			Weight: weights[i%3],
		}

		fmt.Printf("node:%#v\n", node)
		nodes = append(nodes, node)
	}

	countStat := make(map[string]int)
	for i := 0; i < 1000; i++ {
		node, err := balance.Select(context.TODO(), nodes)
		if err != nil {
			t.Fatalf("select failed, err:%v", err)
			continue
		}

		countStat[node.IP]++
	}

	for key, val := range countStat {
		fmt.Printf("ip:%s count:%v\n", key, val)
	}
	return
}
发布了166 篇原创文章 · 获赞 26 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/qq_28710983/article/details/93337167