Merge pull request #891 from andrewhamon/policy-cleanup

Refactor and clean up policy code
This commit is contained in:
Matt Holt 2016-06-20 09:27:48 -06:00 committed by GitHub
commit 807617965a

View File

@ -1,6 +1,7 @@
package proxy package proxy
import ( import (
"math"
"math/rand" "math/rand"
"sync" "sync"
) )
@ -24,22 +25,23 @@ type Random struct{}
// Select selects an up host at random from the specified pool. // Select selects an up host at random from the specified pool.
func (r *Random) Select(pool HostPool) *UpstreamHost { func (r *Random) Select(pool HostPool) *UpstreamHost {
// instead of just generating a random index
// this is done to prevent selecting a unavailable host // Because the number of available hosts isn't known
// up front, the host is selected via reservoir sampling
// https://en.wikipedia.org/wiki/Reservoir_sampling
var randHost *UpstreamHost var randHost *UpstreamHost
count := 0 count := 0
for _, host := range pool { for _, host := range pool {
if !host.Available() { if !host.Available() {
continue continue
} }
// (n % 1 == 0) holds for all n, therefore randHost
// will always get assigned a value if there is
// at least 1 available host
count++ count++
if count == 1 { if (rand.Int() % count) == 0 {
randHost = host randHost = host
} else {
r := rand.Int() % count
if r == (count - 1) {
randHost = host
}
} }
} }
return randHost return randHost
@ -54,26 +56,23 @@ type LeastConn struct{}
func (r *LeastConn) Select(pool HostPool) *UpstreamHost { func (r *LeastConn) Select(pool HostPool) *UpstreamHost {
var bestHost *UpstreamHost var bestHost *UpstreamHost
count := 0 count := 0
leastConn := int64(1<<63 - 1) leastConn := int64(math.MaxInt64)
for _, host := range pool { for _, host := range pool {
if !host.Available() { if !host.Available() {
continue continue
} }
hostConns := host.Conns
if hostConns < leastConn { if host.Conns < leastConn {
bestHost = host leastConn = host.Conns
leastConn = hostConns count = 0
count = 1 }
} else if hostConns == leastConn {
// randomly select host among hosts with least connections // Among hosts with same least connections, perform a reservoir
// sample: https://en.wikipedia.org/wiki/Reservoir_sampling
if host.Conns == leastConn {
count++ count++
if count == 1 { if (rand.Int() % count) == 0 {
bestHost = host bestHost = host
} else {
r := rand.Int() % count
if r == (count - 1) {
bestHost = host
}
} }
} }
} }