serverload.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package sdk
  2. import (
  3. "github.com/mhaya/game/game_cluster/internal/data"
  4. mhayaLogger "github.com/mhaya/logger"
  5. "math/rand"
  6. )
  7. // Service 结构体表示单个服务的信息。
  8. type Service struct {
  9. NodeId string // 服务的节点地址
  10. Player int
  11. Weight float64 // 权重
  12. }
  13. // WeightedRoundRobin 是一个结构体,用于管理一组带权重的服务,并支持基于权重的选择逻辑。
  14. type WeightedRoundRobin struct {
  15. services []*Service
  16. all int
  17. total float64 // 所有服务的总权重
  18. }
  19. // NewWeightedRoundRobin 创建一个新的 WeightedRoundRobin 实例。
  20. func NewWeightedRoundRobin(maps map[string]int) *WeightedRoundRobin {
  21. serviceConfig, ok := data.ServerConfig.Get()
  22. if !ok {
  23. mhayaLogger.Warnf("[NewWeightedRoundRobin] weighted round robin service config is nil")
  24. return nil
  25. }
  26. wrr := &WeightedRoundRobin{
  27. services: nil,
  28. }
  29. var services []*Service
  30. for k, v := range maps {
  31. wrr.all += v
  32. services = append(services, &Service{
  33. NodeId: k,
  34. Player: v,
  35. })
  36. }
  37. wrr.services = services
  38. avg := wrr.all / len(wrr.services)
  39. for _, service := range services {
  40. if service.Player-avg <= 3*serviceConfig.Range {
  41. service.Weight = float64(serviceConfig.Weight.Max)
  42. } else if service.Player-avg < 2*serviceConfig.Range {
  43. service.Weight = float64(serviceConfig.Weight.Middle)
  44. } else {
  45. service.Weight = float64(serviceConfig.Weight.Min)
  46. }
  47. if service.Player >= serviceConfig.Expansion {
  48. service.Weight = float64(serviceConfig.Weight.Min)
  49. }
  50. if service.Player >= serviceConfig.Max {
  51. service.Weight = 0
  52. }
  53. }
  54. for _, s := range services {
  55. wrr.total += s.Weight
  56. }
  57. return wrr
  58. }
  59. // Pick 使用加权轮询的方式选取一个服务。
  60. func (w *WeightedRoundRobin) Pick() *Service {
  61. if len(w.services) == 0 {
  62. return nil
  63. }
  64. // 随机选择一个介于[0, total)之间的数字
  65. target := rand.Float64() * w.total
  66. var current float64 = 0.0
  67. // 循环直到找到正确的服务
  68. for _, service := range w.services {
  69. current += service.Weight
  70. if current >= target {
  71. return service
  72. }
  73. }
  74. // 如果因浮点数精度问题未能命中,则返回最后一个服务
  75. return w.services[len(w.services)-1]
  76. }