xorm/engine_group_policy.go

149 lines
2.9 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 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 03:26:06 +00:00
type RandomPolicy struct {
r *rand.Rand
2017-09-26 01:45:51 +00:00
}
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 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 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
}
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
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
}
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
}
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++
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 03:26:06 +00:00
type LeastConnPolicy struct {
2017-09-26 01:45:51 +00:00
}
2017-09-26 03:26:06 +00:00
func NewLeastConnPolicy() *LeastConnPolicy {
return &LeastConnPolicy{}
}
func (policy *LeastConnPolicy) Slave(g *EngineGroup) *Engine {
var slaves = g.Slaves()
connections := 0
idx := 0
for i, _ := range slaves {
2017-09-26 05:25:50 +00:00
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
}
}
return slaves[idx]
2017-09-26 01:45:51 +00:00
}