2015-04-15 20:27:55 +00:00
|
|
|
package influxdb
|
|
|
|
|
|
|
|
import (
|
|
|
|
"math/rand"
|
2015-05-27 19:41:58 +00:00
|
|
|
|
|
|
|
"github.com/influxdb/influxdb/meta"
|
2015-04-15 20:27:55 +00:00
|
|
|
)
|
|
|
|
|
2015-05-27 19:41:58 +00:00
|
|
|
// Balancer represents a load-balancing algorithm for a set of nodes
|
2015-04-15 20:27:55 +00:00
|
|
|
type Balancer interface {
|
2015-05-27 19:41:58 +00:00
|
|
|
// Next returns the next Node according to the balancing method
|
2015-04-15 20:27:55 +00:00
|
|
|
// or nil if there are no nodes available
|
2015-05-27 19:41:58 +00:00
|
|
|
Next() *meta.NodeInfo
|
2015-04-15 20:27:55 +00:00
|
|
|
}
|
|
|
|
|
2015-05-27 19:41:58 +00:00
|
|
|
type nodeBalancer struct {
|
|
|
|
nodes []meta.NodeInfo // data nodes to balance between
|
|
|
|
p int // current node index
|
2015-04-15 20:27:55 +00:00
|
|
|
}
|
|
|
|
|
2015-05-27 19:41:58 +00:00
|
|
|
// NewNodeBalancer create a shuffled, round-robin balancer so that
|
2015-04-15 20:27:55 +00:00
|
|
|
// multiple instances will return nodes in randomized order and each
|
2015-05-27 19:41:58 +00:00
|
|
|
// each returned node will be repeated in a cycle
|
|
|
|
func NewNodeBalancer(nodes []meta.NodeInfo) Balancer {
|
|
|
|
// make a copy of the node slice so we can randomize it
|
2015-04-15 20:27:55 +00:00
|
|
|
// without affecting the original instance as well as ensure
|
|
|
|
// that each Balancer returns nodes in a different order
|
2015-05-27 19:41:58 +00:00
|
|
|
b := &nodeBalancer{}
|
|
|
|
|
|
|
|
b.nodes = make([]meta.NodeInfo, len(nodes))
|
|
|
|
copy(b.nodes, nodes)
|
2015-04-15 20:27:55 +00:00
|
|
|
|
|
|
|
b.shuffle()
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
2015-05-27 19:41:58 +00:00
|
|
|
// shuffle randomizes the ordering the balancers available nodes
|
|
|
|
func (b *nodeBalancer) shuffle() {
|
|
|
|
for i := range b.nodes {
|
2015-04-15 20:27:55 +00:00
|
|
|
j := rand.Intn(i + 1)
|
2015-05-27 19:41:58 +00:00
|
|
|
b.nodes[i], b.nodes[j] = b.nodes[j], b.nodes[i]
|
2015-04-15 20:27:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-27 19:41:58 +00:00
|
|
|
// online returns a slice of the nodes that are online
|
|
|
|
func (b *nodeBalancer) online() []meta.NodeInfo {
|
|
|
|
return b.nodes
|
|
|
|
// now := time.Now().UTC()
|
|
|
|
// up := []meta.NodeInfo{}
|
|
|
|
// for _, n := range b.nodes {
|
|
|
|
// if n.OfflineUntil.After(now) {
|
|
|
|
// continue
|
|
|
|
// }
|
|
|
|
// up = append(up, n)
|
|
|
|
// }
|
|
|
|
// return up
|
2015-04-15 20:27:55 +00:00
|
|
|
}
|
|
|
|
|
2015-05-27 19:41:58 +00:00
|
|
|
// Next returns the next available nodes
|
|
|
|
func (b *nodeBalancer) Next() *meta.NodeInfo {
|
2015-04-15 20:27:55 +00:00
|
|
|
// only use online nodes
|
|
|
|
up := b.online()
|
|
|
|
|
|
|
|
// no nodes online
|
|
|
|
if len(up) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// rollover back to the beginning
|
|
|
|
if b.p >= len(up) {
|
|
|
|
b.p = 0
|
|
|
|
}
|
|
|
|
|
2015-05-27 19:41:58 +00:00
|
|
|
d := &up[b.p]
|
2015-10-06 04:10:25 +00:00
|
|
|
b.p++
|
2015-04-15 20:27:55 +00:00
|
|
|
|
|
|
|
return d
|
|
|
|
}
|