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()
}
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]