请选择 进入手机版 | 继续访问电脑版

[Golang] 利用 Golang实现加权负载平衡 算法的实当代 码

  [复制链接]
查看338 | 回复71 | 2021-9-15 04:21:59 | 显示全部楼层 |阅读模式

背景形貌

如下图所示,负载平衡 做为反向代理,将哀求 方的哀求 转发至后端的服务节点,实现服务的哀求 。

利用
Golang实现加权负载平衡
算法的实当代
码

在nginx中可以通过upstream设置 server时,设置weight表示对应server的权重。

若存在多个服务节点时,负载平衡 怎样 通过服务节点的权重举行 转发。

如下具体 阐明 权重转发算法的实现。

用三个后端服务节点为例阐明

设置三个后端服务ServerA,ServerB和ServerC,它们的权重分布是 5,3,1

按照加权负载平衡 算法,在一轮(5+3+1=9次)中ServerA占5次,ServerB占3次,ServerC占1次,从而实现平衡 。

如下图所示:

利用
Golang实现加权负载平衡
算法的实当代
码

为了实现这个功能,可以给每一个后端设置对应的权重5,3,1

变量1:后端服务的权重 Weight

变量2:平衡 器累计的总的有用 权重EffectiveWeight

变量3:及时 统计后端服务的当前权重 CurrentWeight

算法计划

第一步,向平衡 器中增长 后端服务标识

  • 将三个后端服务标识和权重Weight增长 到负载平衡 器列表中。
  • 每次增长 后端服务时,累计总的有用 权重EffectiveWeight。

第二步,每次获取一个后端服务标识

  • 对平衡 器中的全部 后端服务增长 本身 的权重Weight,即(5,3,1),计算ABC三个服务的当前权重。
  • 选择当前权重CurrentWeight最大的服务,做为本次盼望 的后端服务。
  • 将盼望 的后端服务的当前权重CurrentWeight减小总的权重EffectiveWeight,供下一轮利用 。

如下是一个一轮(5+3+1=9次)获取的权重变化表:

利用
Golang实现加权负载平衡
算法的实当代
码

从这个表中可以看到后端服务轮询的次序 是 A B A C A B A B A,此中 A出现了5次,B出现了3次,C出现了1次,满足 三个服务的权重Weight设置。

完成9次获取后,ABC三个服务的权重都归0,因此下一轮的9次获取也是平衡 的,

算法实现

按照如上算法阐明 ,利用 Golang实现这个算法如下

  1. package weightroundrobin
  2. import (
  3. "fmt"
  4. "strings"
  5. )
  6. // 每一个后端服务定义
  7. type BackendServer struct {
  8. // 实例权重
  9. Weight int
  10. // 当前的权重,初始为Weight
  11. currentWeight int
  12. // 后端服务名称
  13. ServerName string
  14. }
  15. // 通过权重实现调用轮询的定义
  16. type WeightServerRoundRobin struct {
  17. // 所有有效的权重总和
  18. effectiveWeight int
  19. // 后端服务列表
  20. backendServerList []*BackendServer
  21. }
  22. // 创建一个负载轮询器
  23. func NewWeightServerRoundRobin() *WeightServerRoundRobin {
  24. return &WeightServerRoundRobin{
  25. effectiveWeight: 0,
  26. }
  27. }
  28. // 增加后端服务名称和权重
  29. func (r *WeightServerRoundRobin) AddBackendServer(backendServer *BackendServer) {
  30. r.effectiveWeight += backendServer.Weight
  31. r.backendServerList = append(r.backendServerList, backendServer)
  32. }
  33. // 更具权重获取一个后端服务名称
  34. func (r *WeightServerRoundRobin) GetBackendServer() *BackendServer {
  35. var expectBackendServer *BackendServer
  36. for _, backendServer := range r.backendServerList {
  37. // 给每个后端服务增加自身权重
  38. backendServer.currentWeight += backendServer.Weight
  39. if expectBackendServer == nil {
  40. expectBackendServer = backendServer
  41. }
  42. if backendServer.currentWeight > expectBackendServer.currentWeight {
  43. expectBackendServer = backendServer
  44. }
  45. }
  46. r.VisitBackendServerCurrentWeight()
  47. // 把选择的后端服务权重减掉总权重
  48. expectBackendServer.currentWeight -= r.effectiveWeight
  49. return expectBackendServer
  50. }
  51. // 打印后端服务的当前权重变化
  52. func (r *WeightServerRoundRobin) VisitBackendServerCurrentWeight() {
  53. var serverListForLog []string
  54. for _, backendServer := range r.backendServerList {
  55. serverListForLog = append(serverListForLog,
  56. fmt.Sprintf("%v", backendServer.currentWeight))
  57. }
  58. fmt.Printf("(%v)\n", strings.Join(serverListForLog, ", "))
  59. }
复制代码

写一个单测举行 验证

  1. package weightroundrobin
  2. import (
  3. "fmt"
  4. "testing"
  5. )
  6. func TestNewWeightServerRoundRobin(t *testing.T) {
  7. weightServerRoundRobin := NewWeightServerRoundRobin()
  8. weightServerRoundRobin.AddBackendServer(&BackendServer{
  9. ServerName: "ServerA",
  10. Weight: 5,
  11. })
  12. weightServerRoundRobin.AddBackendServer(&BackendServer{
  13. ServerName: "ServerB",
  14. Weight: 3,
  15. })
  16. weightServerRoundRobin.AddBackendServer(&BackendServer{
  17. ServerName: "ServerC",
  18. Weight: 1,
  19. })
  20. expectServerNameList := []string{
  21. "ServerA", "ServerB", "ServerA", "ServerC", "ServerA", "ServerB", "ServerA", "ServerB", "ServerA",
  22. //"ServerA", "ServerB", "ServerA", "ServerC", "ServerA", "ServerB", "ServerA", "ServerB", "ServerA",
  23. }
  24. fmt.Printf("(A, B, C)\n")
  25. for ii, expectServerName := range expectServerNameList {
  26. weightServerRoundRobin.VisitBackendServerCurrentWeight()
  27. backendServer := weightServerRoundRobin.GetBackendServer()
  28. if backendServer.ServerName != expectServerName {
  29. t.Errorf("%v.%v.expect:%v, actual:%v", t.Name(), ii, expectServerName, backendServer.ServerName)
  30. return
  31. }
  32. }
  33. }
复制代码

运行单元测试,观察运行效果 是否符合算法计划 的预期

  1. === RUN   TestNewWeightServerRoundRobin
  2. (A, B, C)
  3. (0, 0, 0)
  4. (5, 3, 1)
  5. (-4, 3, 1)
  6. (1, 6, 2)
  7. (1, -3, 2)
  8. (6, 0, 3)
  9. (-3, 0, 3)
  10. (2, 3, 4)
  11. (2, 3, -5)
  12. (7, 6, -4)
  13. (-2, 6, -4)
  14. (3, 9, -3)
  15. (3, 0, -3)
  16. (8, 3, -2)
  17. (-1, 3, -2)
  18. (4, 6, -1)
  19. (4, -3, -1)
  20. (9, 0, 0)
  21. --- PASS: TestNewWeightServerRoundRobin (0.00s)
  22. PASS
复制代码

参考材料:

https://github.com/phusion/nginx/commit/27e94984486058d73157038f7950a0a36ecc6e35

到此这篇关于利用 Golang实现加权负载平衡 算法的文章就先容 到这了,更多干系 Golang负载平衡 算法内容请搜索 脚本之家从前 的文章或继续欣赏 下面的干系 文章盼望 大家以后多多支持脚本之家!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

avatar 回忆还是面包傲 | 2021-9-15 20:19:49 | 显示全部楼层
admin楼主的帖子提神醒脑啊!
回复

使用道具 举报

avatar 精诚通潭 | 2021-9-15 21:16:12 | 显示全部楼层
坚持回帖!
回复

使用道具 举报

avatar 荷叶224 | 2021-9-15 23:07:03 | 显示全部楼层
学习雷锋,好好回帖!
回复

使用道具 举报

avatar 123457660 | 2021-9-16 02:54:03 | 显示全部楼层
支持一下!
回复

使用道具 举报

avatar 尔己乡变她 | 2021-9-16 15:18:54 | 显示全部楼层
突然觉得admin楼主说的很有道理,赞一个!
回复

使用道具 举报

avatar 北右酝 | 2021-9-21 06:09:44 | 显示全部楼层
我就搞不明白了,看帖回帖能死人么,居然只有我这么认真的在回帖!
回复

使用道具 举报

avatar 贺长云 | 2021-9-25 13:16:39 | 显示全部楼层
刚分手,心情不好!
回复

使用道具 举报

avatar 清风JA1 | 2021-9-26 20:27:28 | 显示全部楼层
admin楼主的等级很高啊!
回复

使用道具 举报

avatar 淡然一笑wwc | 2021-9-29 10:11:46 | 显示全部楼层
这么版块的帖子越来越有深度了!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则