-
Notifications
You must be signed in to change notification settings - Fork 0
/
backend_names.go
110 lines (97 loc) · 2.22 KB
/
backend_names.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package main
import (
"net"
"sync"
"github.com/google/gopacket/layers"
"stathat.com/c/consistent"
)
type backend struct {
Name string
IP net.IP
Port uint16
HealthChecker instanceHealthChecker
healthy bool
}
func (b backend) isHealthy() bool {
return b.healthy
}
var backendincomingPacket = make(chan *layers.GRE)
//backendPool, is the pool for backend
type backendPool struct {
pool []backend
//healthchecker
healthChecker instanceHealthChecker
//for load balancing
consistency *consistent.Consistent
//to avoid race condition
*sync.RWMutex
}
//onlyHealty, returns only healthy backends
func (p backendPool) onlyHealty() backendPool {
p.RLock()
defer p.RUnlock()
var h = make([]backend, len(p.pool))
var count = 0
for _, v := range p.pool {
if v.healthy {
h[count] = v
count++
}
}
return backendPool{pool: h[:count]}
}
//add, adds new backend instance
//healthchecking method is same for instances in a backend pool
//instance is in unhealthy state untill its first health check success
func (p *backendPool) add(b backend) {
p.Lock()
defer p.Unlock()
b.HealthChecker = p.healthChecker
p.pool = append(p.pool, b)
}
//remove, removes backend from the backend pool
//It uses backend ip for matching
//Returns removed backend
func (p *backendPool) remove(b backend) backend {
p.Lock()
defer p.Unlock()
var pool = make([]backend, len(p.pool))
var r backend
count := 0
for _, v := range p.pool {
if v.Name == b.Name {
r = v
p.consistency.Remove(b.Name)
continue
} else {
pool[count] = v
count++
}
}
p.pool = pool[:count]
return r
}
//markHealthy, marks a backend instance healthy so it listen traffic
func (p backendPool) markHealthy(b backend) {
p.Lock()
defer p.Unlock()
for _, v := range p.pool {
if v.Name == b.Name && !v.healthy {
v.healthy = true
p.consistency.Add(b.Name) //Removing from load balancer
break
}
}
}
//markUnHealthy, marks a backend instance unhealthy lb stops forwarding load on it
func (p backendPool) markUnHealthy(b backend) {
p.Lock()
defer p.Unlock()
for _, v := range p.pool {
if v.Name == b.Name && v.healthy {
v.healthy = false
p.consistency.Remove(b.Name) //Adding to listen load balancer
break
}
}
}