mirror of
https://github.com/caddyserver/caddy.git
synced 2024-11-25 17:56:34 +08:00
Merge pull request #891 from andrewhamon/policy-cleanup
Refactor and clean up policy code
This commit is contained in:
commit
807617965a
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user