xorm/engine_group_policy.go

117 lines
2.6 KiB
Go
Raw Normal View History

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
// 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 12:41:34 +00:00
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()))]
2017-09-26 03:26:06 +00:00
}
2017-09-26 02:22:13 +00:00
}
2017-09-26 11:58:43 +00:00
// WeightRandomPolicy implmentes randomly chose the slave of slaves
2017-09-26 12:41:34 +00:00
func WeightRandomPolicy(weights []int) GroupPolicyHandler {
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 12:41:34 +00:00
var r = rand.New(rand.NewSource(time.Now().UnixNano()))
2017-09-26 01:45:51 +00:00
2017-09-26 12:41:34 +00:00
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]
2017-09-26 01:45:51 +00:00
}
2017-09-26 03:26:06 +00:00
}
2017-09-26 12:41:34 +00:00
func RoundRobinPolicy() GroupPolicyHandler {
var pos = -1
var lock sync.Mutex
return func(g *EngineGroup) *Engine {
var slaves = g.Slaves()
2017-09-26 01:45:51 +00:00
2017-09-26 12:41:34 +00:00
lock.Lock()
defer lock.Unlock()
pos++
if pos >= len(slaves) {
pos = 0
}
2017-09-26 01:45:51 +00:00
2017-09-26 12:41:34 +00:00
return slaves[pos]
2017-09-26 01:45:51 +00:00
}
}
2017-09-26 12:41:34 +00:00
func WeightRoundRobinPolicy(weights []int) GroupPolicyHandler {
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 12:41:34 +00:00
var pos = -1
var lock sync.Mutex
2017-09-26 01:45:51 +00:00
2017-09-26 12:41:34 +00:00
return func(g *EngineGroup) *Engine {
var slaves = g.Slaves()
lock.Lock()
defer lock.Unlock()
pos++
if pos >= len(rands) {
pos = 0
}
2017-09-26 01:45:51 +00:00
2017-09-26 12:41:34 +00:00
idx := rands[pos]
if idx >= len(slaves) {
idx = len(slaves) - 1
}
return slaves[idx]
2017-09-26 01:45:51 +00:00
}
2017-09-26 03:26:06 +00:00
}
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 12:13:49 +00:00
return slaves[idx]
}
2017-09-26 01:45:51 +00:00
}