weightRoundRobin.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package loadmodule
  2. import (
  3. "errors"
  4. "gateway/common/logs"
  5. "github.com/gogf/gf/v2/os/gctx"
  6. "net/url"
  7. "strconv"
  8. "strings"
  9. )
  10. type WeightRoundRobinProxy struct {
  11. curIndex int
  12. rss []*WeightNode
  13. rsw []int
  14. }
  15. type WeightNode struct {
  16. addr *url.URL
  17. weight int //权重值
  18. currentWeight int //节点当前权重
  19. effectiveWeight int //有效权重
  20. }
  21. func (r *WeightRoundRobinProxy) Add(param string) error {
  22. params := strings.Split(param, "|")
  23. if len(params) != 2 {
  24. return errors.New("param len need 2")
  25. }
  26. parInt, err := strconv.ParseInt(params[1], 10, 64)
  27. if err != nil {
  28. return err
  29. }
  30. remoteUrl, err := url.Parse(strings.TrimSpace(params[0]))
  31. if err != nil {
  32. return err
  33. }
  34. node := &WeightNode{addr: remoteUrl, weight: int(parInt)}
  35. node.effectiveWeight = node.weight
  36. r.rss = append(r.rss, node)
  37. return nil
  38. }
  39. func (r *WeightRoundRobinProxy) Next() *url.URL {
  40. if len(r.rss) == 1 {
  41. return r.rss[0].addr
  42. }
  43. total := 0
  44. var best *WeightNode
  45. for i := 0; i < len(r.rss); i++ {
  46. w := r.rss[i]
  47. //step 1 统计所有有效权重之和
  48. total += w.effectiveWeight
  49. //step 2 变更节点临时权重为的节点临时权重+节点有效权重
  50. w.currentWeight += w.effectiveWeight
  51. //step 3 有效权重默认与权重相同,通讯异常时-1, 通讯成功+1,直到恢复到weight大小
  52. if w.effectiveWeight < w.weight {
  53. w.effectiveWeight++
  54. }
  55. //step 4 选择最大临时权重点节点
  56. if best == nil || w.currentWeight > best.currentWeight {
  57. best = w
  58. }
  59. }
  60. if best == nil {
  61. logs.GInfo.Info(gctx.New(), "WeightRoundRobinProxy 获取权重异常 ")
  62. return r.rss[0].addr
  63. }
  64. //step 5 变更临时权重为 临时权重-有效权重之和
  65. best.currentWeight -= total
  66. return best.addr
  67. }
  68. func (r *WeightRoundRobinProxy) Get() *url.URL {
  69. return r.Next()
  70. }
  71. func (r *WeightRoundRobinProxy) Len() int {
  72. return len(r.rss)
  73. }
  74. func (r *WeightRoundRobinProxy) Update() {
  75. }