Golang加权轮询负载均衡的实现

时间:2022-09-10 08:35:34

实现加权轮询负载均衡思路

代码实现一个加权负载均衡

  • Weight            初始化时对节点约定的权重
  • currentWeight     节点临时权重,每轮都会变化
  • effectiveWeight   节点有效权重,默认与Weight相同
  • totalWeight       所有节点有效权重之和:sum(effectiveWeight)

代码实现一个加权负载均衡

  • currentWeight = currentWeight+effecitveWeight
  • 选中最大的 currentWeight 节点为选中节点
  • currentWeight = currentWeight-totalWeight  (4+3+2=9)

所以我们能够 在表格模拟运行情况:

 

请求次数 请求前currentWelght 选中的节点 请求后currentWelght
1 [serverA=4,serverB=3,serverC=2] serverA [serverA=-1,serverB=6,serverC=4]
2 [serverA=-1,serverB=6,serverC=4] serverB [serverA=3,serverB=0,serverC=6]
3 [serverA=3,serverB=0,serverC=6] serverc [serverA=7,serverB=3,serverC=-1]
4 [serverA=7,serverB=3,serverC=-1] serverA [serverA=2,serverB=6,serverC=1]
5 [serverA=2,serverB=6,serverC=1] serverB [serverA=6,serverB=0,serverC=3]
6 [serverA=6,serverB=0,serverC=3] serverA [serverA=1,serverB=3,serverC=5]
7 [serverA=1,serverB=3,serverC=5] serverc [serverA=5,serverB=6,serverC=-2]

 

加权轮询负载均衡代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package load_balance
 
import (
 "errors"
 "strconv"
 
)
 
type WeightRoundRobinBalance struct {
 curIndex int
 rss      []*WeightNode
 rsw      []int
 
 //观察主体
 conf LoadBalanceConf
}
 
// 配置主题
type LoadBalanceConf interface {
 GetConf() []string
 WatchConf()
 UpdateConf(conf []string)
}
 
type WeightNode struct {
 addr            string // 服务器地址
 weight          int //权重值
 currentWeight   int //节点当前权重
 effectiveWeight int //有效权重
}
 
func (r *WeightRoundRobinBalance) Add(params ...string) error {
 if len(params) != 2 {
  return errors.New("param len need 2")
 }
 parInt, err := strconv.ParseInt(params[1], 10, 64)
 if err != nil {
  return err
 }
 node := &WeightNode{addr: params[0], weight: int(parInt)}
 node.effectiveWeight = node.weight
 r.rss = append(r.rss, node)
 return nil
}
 
func (r *WeightRoundRobinBalance) Next() string {
 total := 0
 var best *WeightNode
 for i := 0; i < len(r.rss); i++ {
  w := r.rss[i]
  //step 1 统计所有有效权重之和
  total += w.effectiveWeight
 
  //step 2 变更节点临时权重为的节点临时权重+节点有效权重
  w.currentWeight += w.effectiveWeight
 
  //step 3 有效权重默认与权重相同,通讯异常时-1, 通讯成功+1,直到恢复到weight大小
  if w.effectiveWeight < w.weight {
   w.effectiveWeight++
  }
  //step 4 选择最大临时权重点节点
  if best == nil || w.currentWeight > best.currentWeight {
   best = w
  }
 }
 if best == nil {
  return ""
 }
 //step 5 变更临时权重为 临时权重-有效权重之和
 best.currentWeight -= total
 return best.addr
}
 
func (r *WeightRoundRobinBalance) Get(key string) (string, error) {
 return r.Next(), nil
}
 
func (r *WeightRoundRobinBalance) SetConf(conf LoadBalanceConf) {
 r.conf = conf
}

测试代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package load_balance
 
import (
 "fmt"
 "testing"
)
 
func TestLB(t *testing.T) {
 rb := &WeightRoundRobinBalance{}
 rb.Add("127.0.0.1:2003", "4") //0
 // rb.Add("127.0.0.1:2004", "3") //1
 rb.Add("127.0.0.1:2005", "2") //2
 
 fmt.Println(rb.Next())
 fmt.Println(rb.Next())
 fmt.Println(rb.Next())
 fmt.Println(rb.Next())
 fmt.Println(rb.Next())
 fmt.Println(rb.Next())
 fmt.Println(rb.Next())
 fmt.Println(rb.Next())
 fmt.Println(rb.Next())
 fmt.Println(rb.Next())
 fmt.Println(rb.Next())
 fmt.Println(rb.Next())
 fmt.Println(rb.Next())
 fmt.Println(rb.Next())
}

测试结果

$ go test
127.0.0.1:2003
127.0.0.1:2005
127.0.0.1:2003
127.0.0.1:2003
127.0.0.1:2005
127.0.0.1:2003
127.0.0.1:2003
127.0.0.1:2005
127.0.0.1:2003
127.0.0.1:2003
127.0.0.1:2005
127.0.0.1:2003
127.0.0.1:2003
127.0.0.1:2005
PASS
ok      gateway/_test/demo      0.080s

## 127.0.0.1:2003 为 127.0.0.1:2005 权重两倍。而从答应结果上看,符合要求

到此这篇关于Golang加权轮询负载均衡的实现的文章就介绍到这了,更多相关Golang加权轮询负载均衡内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家! 

原文链接:https://juejin.cn/post/6974775746807988232