2017-09-26 03:29:41 +00:00
|
|
|
// Copyright 2017 The Xorm Authors. All rights reserved.
|
2017-09-26 01:45:51 +00:00
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package xorm
|
|
|
|
|
|
|
|
import (
|
|
|
|
"math/rand"
|
2017-09-26 03:26:06 +00:00
|
|
|
"sync"
|
2017-09-26 01:45:51 +00:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2017-09-26 11:58:43 +00:00
|
|
|
// GroupPolicy is be used by chosing the current slave from slaves
|
2017-09-26 03:29:41 +00:00
|
|
|
type GroupPolicy interface {
|
2017-09-26 02:22:13 +00:00
|
|
|
Slave(*EngineGroup) *Engine
|
2017-09-26 01:45:51 +00:00
|
|
|
}
|
|
|
|
|
2017-09-26 11:58:43 +00:00
|
|
|
// GroupPolicyHandler should be used when a function is a GroupPolicy
|
|
|
|
type GroupPolicyHandler func(*EngineGroup) *Engine
|
|
|
|
|
2017-09-26 12:05:07 +00:00
|
|
|
// Slave implements the chosen of slaves
|
|
|
|
func (h GroupPolicyHandler) Slave(eg *EngineGroup) *Engine {
|
|
|
|
return h(eg)
|
|
|
|
}
|
|
|
|
|
2017-09-26 11:58:43 +00:00
|
|
|
// RandomPolicy implmentes randomly chose the slave of slaves
|
2017-09-26 03:26:06 +00:00
|
|
|
type RandomPolicy struct {
|
|
|
|
r *rand.Rand
|
2017-09-26 01:45:51 +00:00
|
|
|
}
|
|
|
|
|
2017-09-26 11:58:43 +00:00
|
|
|
// NewRandomPolicy creates a RandomPolicy
|
2017-09-26 03:26:06 +00:00
|
|
|
func NewRandomPolicy() *RandomPolicy {
|
|
|
|
return &RandomPolicy{
|
|
|
|
r: rand.New(rand.NewSource(time.Now().UnixNano())),
|
|
|
|
}
|
2017-09-26 02:22:13 +00:00
|
|
|
}
|
|
|
|
|
2017-09-26 11:58:43 +00:00
|
|
|
// Slave randomly choses the slave of slaves
|
2017-09-26 03:26:06 +00:00
|
|
|
func (policy *RandomPolicy) Slave(g *EngineGroup) *Engine {
|
|
|
|
return g.Slaves()[policy.r.Intn(len(g.Slaves()))]
|
2017-09-26 01:45:51 +00:00
|
|
|
}
|
|
|
|
|
2017-09-26 11:58:43 +00:00
|
|
|
// WeightRandomPolicy implmentes randomly chose the slave of slaves
|
2017-09-26 03:26:06 +00:00
|
|
|
type WeightRandomPolicy struct {
|
|
|
|
weights []int
|
|
|
|
rands []int
|
|
|
|
r *rand.Rand
|
2017-09-26 01:45:51 +00:00
|
|
|
}
|
|
|
|
|
2017-09-26 03:26:06 +00:00
|
|
|
func NewWeightRandomPolicy(weights []int) *WeightRandomPolicy {
|
|
|
|
var rands = make([]int, 0, len(weights))
|
|
|
|
for i := 0; i < len(weights); i++ {
|
|
|
|
for n := 0; n < weights[i]; n++ {
|
|
|
|
rands = append(rands, i)
|
|
|
|
}
|
2017-09-26 01:45:51 +00:00
|
|
|
}
|
|
|
|
|
2017-09-26 03:26:06 +00:00
|
|
|
return &WeightRandomPolicy{
|
|
|
|
weights: weights,
|
|
|
|
rands: rands,
|
|
|
|
r: rand.New(rand.NewSource(time.Now().UnixNano())),
|
|
|
|
}
|
2017-09-26 01:45:51 +00:00
|
|
|
}
|
|
|
|
|
2017-09-26 03:26:06 +00:00
|
|
|
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
|
2017-09-26 01:45:51 +00:00
|
|
|
}
|
2017-09-26 03:26:06 +00:00
|
|
|
return slaves[idx]
|
|
|
|
}
|
|
|
|
|
|
|
|
type RoundRobinPolicy struct {
|
|
|
|
pos int
|
|
|
|
lock sync.Mutex
|
|
|
|
}
|
2017-09-26 01:45:51 +00:00
|
|
|
|
2017-09-26 03:26:06 +00:00
|
|
|
func NewRoundRobinPolicy() *RoundRobinPolicy {
|
|
|
|
return &RoundRobinPolicy{pos: -1}
|
2017-09-26 01:45:51 +00:00
|
|
|
}
|
|
|
|
|
2017-09-26 03:26:06 +00:00
|
|
|
func (policy *RoundRobinPolicy) Slave(g *EngineGroup) *Engine {
|
2017-09-26 04:54:13 +00:00
|
|
|
var slaves = g.Slaves()
|
2017-09-26 03:26:06 +00:00
|
|
|
var pos int
|
|
|
|
policy.lock.Lock()
|
|
|
|
policy.pos++
|
2017-09-26 04:54:13 +00:00
|
|
|
if policy.pos >= len(slaves) {
|
2017-09-26 03:26:06 +00:00
|
|
|
policy.pos = 0
|
2017-09-26 01:45:51 +00:00
|
|
|
}
|
2017-09-26 03:26:06 +00:00
|
|
|
pos = policy.pos
|
|
|
|
policy.lock.Unlock()
|
2017-09-26 01:45:51 +00:00
|
|
|
|
2017-09-26 04:54:13 +00:00
|
|
|
return slaves[pos]
|
2017-09-26 01:45:51 +00:00
|
|
|
}
|
|
|
|
|
2017-09-26 03:36:12 +00:00
|
|
|
type WeightRoundRobinPolicy struct {
|
2017-09-26 03:26:06 +00:00
|
|
|
weights []int
|
|
|
|
rands []int
|
|
|
|
r *rand.Rand
|
|
|
|
lock sync.Mutex
|
|
|
|
pos int
|
|
|
|
}
|
2017-09-26 01:45:51 +00:00
|
|
|
|
2017-09-26 03:36:12 +00:00
|
|
|
func NewWeightRoundRobinPolicy(weights []int) *WeightRoundRobinPolicy {
|
2017-09-26 03:26:06 +00:00
|
|
|
var rands = make([]int, 0, len(weights))
|
|
|
|
for i := 0; i < len(weights); i++ {
|
|
|
|
for n := 0; n < weights[i]; n++ {
|
|
|
|
rands = append(rands, i)
|
|
|
|
}
|
2017-09-26 01:45:51 +00:00
|
|
|
}
|
|
|
|
|
2017-09-26 03:36:12 +00:00
|
|
|
return &WeightRoundRobinPolicy{
|
2017-09-26 03:26:06 +00:00
|
|
|
weights: weights,
|
|
|
|
rands: rands,
|
|
|
|
r: rand.New(rand.NewSource(time.Now().UnixNano())),
|
|
|
|
pos: -1,
|
|
|
|
}
|
2017-09-26 01:45:51 +00:00
|
|
|
}
|
|
|
|
|
2017-09-26 03:36:12 +00:00
|
|
|
func (policy *WeightRoundRobinPolicy) Slave(g *EngineGroup) *Engine {
|
2017-09-26 03:26:06 +00:00
|
|
|
var slaves = g.Slaves()
|
|
|
|
var pos int
|
|
|
|
policy.lock.Lock()
|
|
|
|
policy.pos++
|
2017-09-26 03:36:12 +00:00
|
|
|
if policy.pos >= len(policy.rands) {
|
2017-09-26 03:26:06 +00:00
|
|
|
policy.pos = 0
|
2017-09-26 01:45:51 +00:00
|
|
|
}
|
2017-09-26 03:26:06 +00:00
|
|
|
pos = policy.pos
|
|
|
|
policy.lock.Unlock()
|
2017-09-26 01:45:51 +00:00
|
|
|
|
2017-09-26 03:26:06 +00:00
|
|
|
idx := policy.rands[pos]
|
|
|
|
if idx >= len(slaves) {
|
|
|
|
idx = len(slaves) - 1
|
2017-09-26 01:45:51 +00:00
|
|
|
}
|
2017-09-26 03:26:06 +00:00
|
|
|
return slaves[idx]
|
|
|
|
}
|
2017-09-26 01:45:51 +00:00
|
|
|
|
2017-09-26 11:58:43 +00:00
|
|
|
// LeastConnPolicy implements GroupPolicy, every time will get the least connections slave
|
2017-09-26 12:13:49 +00:00
|
|
|
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
|
|
|
|
}
|
2017-09-26 04:32:21 +00:00
|
|
|
}
|
2017-09-26 12:13:49 +00:00
|
|
|
return slaves[idx]
|
2017-09-26 04:32:21 +00:00
|
|
|
}
|
2017-09-26 01:45:51 +00:00
|
|
|
}
|