Go算法以预定义比例遍历服务器

I am tying to make a algorithm that can loop true things, backend server in my case by a pre defined ratio.

for example I got 2 backend servers

type server struct {
    addr string
    ratio float64
    counter int64
}

// s2 is a beast and may handle 3 times the requests then s1 *edit
s1 := &server{":3000", 0.25}
s2 := &server{":3001", 0.75}

func nextServer() {
    server := next() // simple goroutine that provides the next server between s1 and s2
    N := server.counter / i
    if float64(N) > server.ratio {
        //repeat this function
        return nextServer()
    }

    server.counter += 1
}    

for i := 0; i < 1000; i++ {
    nextServer()
}
  • s1 has 250 as counter (requests handled)
  • s2 is huge so he has 750 as counter (requests handled)

this is a very simple implementation of what I got but when i is like 10000, it keeps looping in nextServer() cause N is always > server.ratio.

as long as i is around 5000 it works perfect. but I think there are better algorithms for looping in ratios.

How to make this simple and solid?

Something like this?

package main

import (
    "fmt"
    "math/rand"
)

type server struct {
    addr  string
    ratio float64
}

var servers []server

func nextServer() *server {
    rndFloat := rand.Float64() //pick a random number between 0.0-1.0
    ratioSum := 0.0
    for _, srv := range servers {
        ratioSum += srv.ratio //sum ratios of all previous servers in list
        if ratioSum >= rndFloat { //if ratiosum rises above the random number
            return &srv //return that server
        }
    }
    return nil //should not come here
}

func main() {
    servers = []server{server{"0.25", 0.25}, server{"0.50", 0.50}, 
            server{"0.10", 0.10}, server{"0.15", 0.15}}

    counts := make(map[string]int, len(servers))
    for i := 0; i < 100; i++ {
        srv := nextServer()
        counts[srv.addr] += 1
    }
    fmt.Println(counts)
}

Yields for example:

map[0.50:56 0.15:15 0.25:24 0.10:5]