|
@@ -10,139 +10,107 @@ import (
|
|
|
"time"
|
|
"time"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+// GroupPolicy is be used by chosing the current slave from slaves
|
|
|
type GroupPolicy interface {
|
|
type GroupPolicy interface {
|
|
|
Slave(*EngineGroup) *Engine
|
|
Slave(*EngineGroup) *Engine
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-type RandomPolicy struct {
|
|
|
|
|
- r *rand.Rand
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-func NewRandomPolicy() *RandomPolicy {
|
|
|
|
|
- return &RandomPolicy{
|
|
|
|
|
- r: rand.New(rand.NewSource(time.Now().UnixNano())),
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
|
|
+// GroupPolicyHandler should be used when a function is a GroupPolicy
|
|
|
|
|
+type GroupPolicyHandler func(*EngineGroup) *Engine
|
|
|
|
|
|
|
|
-func (policy *RandomPolicy) Slave(g *EngineGroup) *Engine {
|
|
|
|
|
- return g.Slaves()[policy.r.Intn(len(g.Slaves()))]
|
|
|
|
|
|
|
+// Slave implements the chosen of slaves
|
|
|
|
|
+func (h GroupPolicyHandler) Slave(eg *EngineGroup) *Engine {
|
|
|
|
|
+ return h(eg)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-type WeightRandomPolicy struct {
|
|
|
|
|
- weights []int
|
|
|
|
|
- rands []int
|
|
|
|
|
- r *rand.Rand
|
|
|
|
|
|
|
+// RandomPolicy implmentes randomly chose the slave of slaves
|
|
|
|
|
+func RandomPolicy() GroupPolicyHandler {
|
|
|
|
|
+ var r = rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
|
|
|
+ return func(g *EngineGroup) *Engine {
|
|
|
|
|
+ return g.Slaves()[r.Intn(len(g.Slaves()))]
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func NewWeightRandomPolicy(weights []int) *WeightRandomPolicy {
|
|
|
|
|
|
|
+// WeightRandomPolicy implmentes randomly chose the slave of slaves
|
|
|
|
|
+func WeightRandomPolicy(weights []int) GroupPolicyHandler {
|
|
|
var rands = make([]int, 0, len(weights))
|
|
var rands = make([]int, 0, len(weights))
|
|
|
for i := 0; i < len(weights); i++ {
|
|
for i := 0; i < len(weights); i++ {
|
|
|
for n := 0; n < weights[i]; n++ {
|
|
for n := 0; n < weights[i]; n++ {
|
|
|
rands = append(rands, i)
|
|
rands = append(rands, i)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ var r = rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
|
|
|
|
|
|
- return &WeightRandomPolicy{
|
|
|
|
|
- weights: weights,
|
|
|
|
|
- rands: rands,
|
|
|
|
|
- r: rand.New(rand.NewSource(time.Now().UnixNano())),
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-func (policy *WeightRandomPolicy) Slave(g *EngineGroup) *Engine {
|
|
|
|
|
- var slaves = g.Slaves()
|
|
|
|
|
- idx := policy.rands[policy.r.Intn(len(policy.rands))]
|
|
|
|
|
- if idx >= len(slaves) {
|
|
|
|
|
- idx = len(slaves) - 1
|
|
|
|
|
|
|
+ return func(g *EngineGroup) *Engine {
|
|
|
|
|
+ var slaves = g.Slaves()
|
|
|
|
|
+ idx := rands[r.Intn(len(rands))]
|
|
|
|
|
+ if idx >= len(slaves) {
|
|
|
|
|
+ idx = len(slaves) - 1
|
|
|
|
|
+ }
|
|
|
|
|
+ return slaves[idx]
|
|
|
}
|
|
}
|
|
|
- return slaves[idx]
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-type RoundRobinPolicy struct {
|
|
|
|
|
- pos int
|
|
|
|
|
- lock sync.Mutex
|
|
|
|
|
-}
|
|
|
|
|
|
|
+func RoundRobinPolicy() GroupPolicyHandler {
|
|
|
|
|
+ var pos = -1
|
|
|
|
|
+ var lock sync.Mutex
|
|
|
|
|
+ return func(g *EngineGroup) *Engine {
|
|
|
|
|
+ var slaves = g.Slaves()
|
|
|
|
|
|
|
|
-func NewRoundRobinPolicy() *RoundRobinPolicy {
|
|
|
|
|
- return &RoundRobinPolicy{pos: -1}
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ lock.Lock()
|
|
|
|
|
+ defer lock.Unlock()
|
|
|
|
|
+ pos++
|
|
|
|
|
+ if pos >= len(slaves) {
|
|
|
|
|
+ pos = 0
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
-func (policy *RoundRobinPolicy) Slave(g *EngineGroup) *Engine {
|
|
|
|
|
- var slaves = g.Slaves()
|
|
|
|
|
- var pos int
|
|
|
|
|
- policy.lock.Lock()
|
|
|
|
|
- policy.pos++
|
|
|
|
|
- if policy.pos >= len(slaves) {
|
|
|
|
|
- policy.pos = 0
|
|
|
|
|
|
|
+ return slaves[pos]
|
|
|
}
|
|
}
|
|
|
- pos = policy.pos
|
|
|
|
|
- policy.lock.Unlock()
|
|
|
|
|
-
|
|
|
|
|
- return slaves[pos]
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-type WeightRoundRobinPolicy struct {
|
|
|
|
|
- weights []int
|
|
|
|
|
- rands []int
|
|
|
|
|
- r *rand.Rand
|
|
|
|
|
- lock sync.Mutex
|
|
|
|
|
- pos int
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-func NewWeightRoundRobinPolicy(weights []int) *WeightRoundRobinPolicy {
|
|
|
|
|
|
|
+func WeightRoundRobinPolicy(weights []int) GroupPolicyHandler {
|
|
|
var rands = make([]int, 0, len(weights))
|
|
var rands = make([]int, 0, len(weights))
|
|
|
for i := 0; i < len(weights); i++ {
|
|
for i := 0; i < len(weights); i++ {
|
|
|
for n := 0; n < weights[i]; n++ {
|
|
for n := 0; n < weights[i]; n++ {
|
|
|
rands = append(rands, i)
|
|
rands = append(rands, i)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ var pos = -1
|
|
|
|
|
+ var lock sync.Mutex
|
|
|
|
|
+
|
|
|
|
|
+ return func(g *EngineGroup) *Engine {
|
|
|
|
|
+ var slaves = g.Slaves()
|
|
|
|
|
+ lock.Lock()
|
|
|
|
|
+ defer lock.Unlock()
|
|
|
|
|
+ pos++
|
|
|
|
|
+ if pos >= len(rands) {
|
|
|
|
|
+ pos = 0
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- return &WeightRoundRobinPolicy{
|
|
|
|
|
- weights: weights,
|
|
|
|
|
- rands: rands,
|
|
|
|
|
- r: rand.New(rand.NewSource(time.Now().UnixNano())),
|
|
|
|
|
- pos: -1,
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-func (policy *WeightRoundRobinPolicy) Slave(g *EngineGroup) *Engine {
|
|
|
|
|
- var slaves = g.Slaves()
|
|
|
|
|
- var pos int
|
|
|
|
|
- policy.lock.Lock()
|
|
|
|
|
- policy.pos++
|
|
|
|
|
- if policy.pos >= len(policy.rands) {
|
|
|
|
|
- policy.pos = 0
|
|
|
|
|
- }
|
|
|
|
|
- pos = policy.pos
|
|
|
|
|
- policy.lock.Unlock()
|
|
|
|
|
-
|
|
|
|
|
- idx := policy.rands[pos]
|
|
|
|
|
- if idx >= len(slaves) {
|
|
|
|
|
- idx = len(slaves) - 1
|
|
|
|
|
|
|
+ idx := rands[pos]
|
|
|
|
|
+ if idx >= len(slaves) {
|
|
|
|
|
+ idx = len(slaves) - 1
|
|
|
|
|
+ }
|
|
|
|
|
+ return slaves[idx]
|
|
|
}
|
|
}
|
|
|
- return slaves[idx]
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-type LeastConnPolicy struct {
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-func NewLeastConnPolicy() *LeastConnPolicy {
|
|
|
|
|
- return &LeastConnPolicy{}
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (policy *LeastConnPolicy) Slave(g *EngineGroup) *Engine {
|
|
|
|
|
- var slaves = g.Slaves()
|
|
|
|
|
- connections := 0
|
|
|
|
|
- idx := 0
|
|
|
|
|
- for i, _ := range slaves {
|
|
|
|
|
- open_connections := slaves[i].DB().Stats().OpenConnections
|
|
|
|
|
- if i == 0 {
|
|
|
|
|
- connections = open_connections
|
|
|
|
|
- idx = i
|
|
|
|
|
- } else if open_connections <= connections {
|
|
|
|
|
- connections = open_connections
|
|
|
|
|
- idx = i
|
|
|
|
|
|
|
+// LeastConnPolicy implements GroupPolicy, every time will get the least connections slave
|
|
|
|
|
+func LeastConnPolicy() GroupPolicyHandler {
|
|
|
|
|
+ return func(g *EngineGroup) *Engine {
|
|
|
|
|
+ var slaves = g.Slaves()
|
|
|
|
|
+ connections := 0
|
|
|
|
|
+ idx := 0
|
|
|
|
|
+ for i := 0; i < len(slaves); i++ {
|
|
|
|
|
+ openConnections := slaves[i].DB().Stats().OpenConnections
|
|
|
|
|
+ if i == 0 {
|
|
|
|
|
+ connections = openConnections
|
|
|
|
|
+ idx = i
|
|
|
|
|
+ } else if openConnections <= connections {
|
|
|
|
|
+ connections = openConnections
|
|
|
|
|
+ idx = i
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
+ return slaves[idx]
|
|
|
}
|
|
}
|
|
|
- return slaves[idx]
|
|
|
|
|
}
|
|
}
|