forked from panjf2000/gnet
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathload_balancing.go
129 lines (108 loc) · 3.19 KB
/
load_balancing.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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Copyright 2019 Andy Pan. All rights reserved.
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
package gnet
// LoadBalancing represents the the type of load-balancing algorithm.
type LoadBalancing int
const (
// RoundRobin assigns the next accepted connection to the event-loop by polling event-loop list.
RoundRobin LoadBalancing = iota
// LeastConnections assigns the next accepted connection to the event-loop that is
// serving the least number of active connections at the current time.
LeastConnections
// SourceAddrHash assignes the next accepted connection to the event-loop by hashing socket fd.
SourceAddrHash
)
// IEventLoopGroup represents a set of event-loops.
type (
IEventLoopGroup interface {
register(*eventloop)
next(int) *eventloop
iterate(func(int, *eventloop) bool)
len() int
}
// roundRobinEventLoopGroup with RoundRobin algorithm.
roundRobinEventLoopGroup struct {
nextLoopIndex int
eventLoops []*eventloop
size int
}
// leastConnectionsEventLoopGroup with Least-Connections algorithm.
leastConnectionsEventLoopGroup []*eventloop
// sourceAddrHashEventLoopGroup with Hash algorithm.
sourceAddrHashEventLoopGroup struct {
eventLoops []*eventloop
size int
}
)
func (g *roundRobinEventLoopGroup) register(el *eventloop) {
g.eventLoops = append(g.eventLoops, el)
g.size++
}
// next returns the eligible event-loop based on Round-Robin algorithm.
func (g *roundRobinEventLoopGroup) next(_ int) (el *eventloop) {
el = g.eventLoops[g.nextLoopIndex]
if g.nextLoopIndex++; g.nextLoopIndex >= g.size {
g.nextLoopIndex = 0
}
return
}
func (g *roundRobinEventLoopGroup) iterate(f func(int, *eventloop) bool) {
for i, el := range g.eventLoops {
if !f(i, el) {
break
}
}
}
func (g *roundRobinEventLoopGroup) len() int {
return g.size
}
func (g *leastConnectionsEventLoopGroup) register(el *eventloop) {
*g = append(*g, el)
}
// next returns the eligible event-loop based on least-connections algorithm.
func (g *leastConnectionsEventLoopGroup) next(_ int) (el *eventloop) {
eventLoops := *g
el = eventLoops[0]
leastConnCount := el.loadConnCount()
var (
curEventLoop *eventloop
curConnCount int32
)
for _, curEventLoop = range eventLoops[1:] {
if curConnCount = curEventLoop.loadConnCount(); curConnCount < leastConnCount {
leastConnCount = curConnCount
el = curEventLoop
}
}
return
}
func (g *leastConnectionsEventLoopGroup) iterate(f func(int, *eventloop) bool) {
eventLoops := *g
for i, el := range eventLoops {
if !f(i, el) {
break
}
}
}
func (g *leastConnectionsEventLoopGroup) len() int {
return len(*g)
}
func (g *sourceAddrHashEventLoopGroup) register(el *eventloop) {
g.eventLoops = append(g.eventLoops, el)
g.size++
}
// next returns the eligible event-loop by taking the remainder of a given fd as the index of event-loop list.
func (g *sourceAddrHashEventLoopGroup) next(hashCode int) *eventloop {
return g.eventLoops[hashCode%g.size]
}
func (g *sourceAddrHashEventLoopGroup) iterate(f func(int, *eventloop) bool) {
for i, el := range g.eventLoops {
if !f(i, el) {
break
}
}
}
func (g *sourceAddrHashEventLoopGroup) len() int {
return g.size
}