1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- package sdk
- import (
- "github.com/mhaya/game/game_cluster/internal/data"
- mhayaLogger "github.com/mhaya/logger"
- "math/rand"
- )
- // Service 结构体表示单个服务的信息。
- type Service struct {
- NodeId string // 服务的节点地址
- Player int
- Weight float64 // 权重
- }
- // WeightedRoundRobin 是一个结构体,用于管理一组带权重的服务,并支持基于权重的选择逻辑。
- type WeightedRoundRobin struct {
- services []*Service
- all int
- total float64 // 所有服务的总权重
- }
- // NewWeightedRoundRobin 创建一个新的 WeightedRoundRobin 实例。
- func NewWeightedRoundRobin(maps map[string]int) *WeightedRoundRobin {
- serviceConfig, ok := data.ServerConfig.Get()
- if !ok {
- mhayaLogger.Warnf("[NewWeightedRoundRobin] weighted round robin service config is nil")
- return nil
- }
- wrr := &WeightedRoundRobin{
- services: nil,
- }
- var services []*Service
- for k, v := range maps {
- wrr.all += v
- services = append(services, &Service{
- NodeId: k,
- Player: v,
- })
- }
- wrr.services = services
- avg := wrr.all / len(wrr.services)
- for _, service := range services {
- if service.Player-avg <= 3*serviceConfig.Range {
- service.Weight = float64(serviceConfig.Weight.Max)
- } else if service.Player-avg < 2*serviceConfig.Range {
- service.Weight = float64(serviceConfig.Weight.Middle)
- } else {
- service.Weight = float64(serviceConfig.Weight.Min)
- }
- if service.Player >= serviceConfig.Expansion {
- service.Weight = float64(serviceConfig.Weight.Min)
- }
- if service.Player >= serviceConfig.Max {
- service.Weight = 0
- }
- }
- for _, s := range services {
- wrr.total += s.Weight
- }
- return wrr
- }
- // Pick 使用加权轮询的方式选取一个服务。
- func (w *WeightedRoundRobin) Pick() *Service {
- if len(w.services) == 0 {
- return nil
- }
- // 随机选择一个介于[0, total)之间的数字
- target := rand.Float64() * w.total
- var current float64 = 0.0
- // 循环直到找到正确的服务
- for _, service := range w.services {
- current += service.Weight
- if current >= target {
- return service
- }
- }
- // 如果因浮点数精度问题未能命中,则返回最后一个服务
- return w.services[len(w.services)-1]
- }
|