Golang加权轮询负载均衡的实现
更新时间:2021年6月18日 15:01 点击:2319
实现加权轮询负载均衡思路
代码实现一个加权负载均衡
- 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 权重两倍。而从答应结果上看,符合要求
到此这篇关于Golang加权轮询负载均衡的实现的文章就介绍到这了,更多相关Golang加权轮询负载均衡内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!
上一篇: Go 容器遍历的实现示例
下一篇: golang中对"引用传递"的误解
相关文章
- 这篇文章主要介绍了golang 调用 php7详解及实例的相关资料,需要的朋友可以参考下...2017-01-15
- 这篇文章主要介绍了用golang实现替换某个文件中的字符串操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-25
- 这篇文章主要介绍了docker swarm外部验证负载均衡时不生效的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-04-27
- 这篇文章主要介绍了golang在GRPC中设置client的超时时间,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-27
- 这篇文章主要介绍了解决Golang json序列化字符串时多了\的情况,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-12-24
- 这篇文章主要介绍了Spring Cloud负载均衡及远程调用实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2021-09-18
Golang中的自定义类型之间的转换的实现(type conversion)
这篇文章主要介绍了Golang中的自定义类型之间的转换的实现(type conversion),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-21- 这篇文章主要介绍了golang与php实现计算两个经纬度之间距离的方法,结合实例形式对比分析了Go语言与php进行经纬度计算的相关数学运算技巧,需要的朋友可以参考下...2016-07-29
解决golang处理http response碰到的问题和需要注意的点
这篇文章主要介绍了解决golang处理http response碰到的问题和需要注意的点,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-12-16- 这篇文章主要介绍了golang http使用踩过的坑与填坑指南,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-27
- 这篇文章主要介绍了golang文件读取-按指定BUFF大小读取方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-12-22
- Go(又称Golang)是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。这篇文章给大家介绍golang 正则表达式的相关知识,感兴趣的朋友跟随小编一起看看吧...2021-05-07
- 这次文章为大家带来的是一个比较实用的示例:利用Golang生成整数随机数,对此感兴趣的可以一起来看看。 php随机数生成一个给定范围的随机数,用 PHP 就太简单不过了,而...2017-07-06
- 这篇文章主要介绍了golang DNS服务器的简单实现操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-05-01
- 这篇文章主要介绍了golang中json和struct的使用说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-05-01
Fedora14 Linux系统安装Golang开发环境笔记
这篇文章主要介绍了Fedora14 Linux系统安装Golang开发环境笔记,本文讲解了2种安装方法,需要的朋友可以参考下...2020-05-01- 这篇文章主要介绍了golang去除多余空白字符(含制表符)的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-25
golang elasticsearch Client的使用详解
这篇文章主要介绍了golang elasticsearch Client的使用详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-05-04- 这篇文章主要介绍了解决golang json解析出现值为空的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-12-24
- 这篇文章主要介绍了golang中的空接口使用,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-03-30