当前位置 博文首页 > Golang加权轮询负载均衡的实现

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

    作者:锐玩道 时间:2021-08-02 18:00

    目录
    • 实现加权轮询负载均衡思路
    • 加权轮询负载均衡代码
    • 测试代码

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

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

    • 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]

    加权轮询负载均衡代码

    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
    }

    测试代码

    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 权重两倍。而从答应结果上看,符合要求

    jsjbwy
    下一篇:没有了