forked from adrianco/spigo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
elb.go
88 lines (86 loc) · 3 KB
/
elb.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
// Package elb simulates an Elastic Load Balancer
// Takes incoming traffic and spreads it over microservices in three availability zones
package elb
import (
"github.com/adrianco/spigo/archaius"
"github.com/adrianco/spigo/gotocol"
"log"
"math/rand"
"time"
)
// Start the elb, all configuration and state is sent via messages
func Start(listener chan gotocol.Message) {
dunbar := 30 // starting point for how many nodes to remember
// remember the channel to talk to microservices
microservices := make(map[string]chan gotocol.Message, dunbar)
microindex := make([]chan gotocol.Message, dunbar)
var netflixoss chan gotocol.Message // remember how to talk back to creator
var name string // remember my name
var edda chan gotocol.Message // if set, send updates
var chatrate time.Duration
chatTicker := time.NewTicker(time.Hour)
chatTicker.Stop()
for {
select {
case msg := <-listener:
if archaius.Conf.Msglog {
log.Printf("%v: %v\n", name, msg)
}
switch msg.Imposition {
case gotocol.Hello:
if name == "" {
// if I don't have a name yet remember what I've been named
netflixoss = msg.ResponseChan // remember how to talk to my namer
name = msg.Intention // message body is my name
}
case gotocol.Inform:
// remember where to send updates
edda = msg.ResponseChan
// logger channel is buffered so no need to use GoSend
edda <- gotocol.Message{gotocol.Hello, nil, time.Now(), name + " " + "elb"}
case gotocol.NameDrop:
// don't remember too many buddies and don't talk to myself
microservice := msg.Intention // message body is buddy name
if len(microservices) < dunbar && microservice != name {
// remember how to talk to this buddy
microservices[microservice] = msg.ResponseChan // message channel is buddy's listener
if edda != nil {
// if it's setup, tell the logger I have a new buddy to talk to
edda <- gotocol.Message{gotocol.Inform, listener, time.Now(), name + " " + microservice}
}
}
case gotocol.Chat:
// setup the ticker to run at the specified rate
d, e := time.ParseDuration(msg.Intention)
if e == nil && d >= time.Millisecond && d <= time.Hour {
chatrate = d
chatTicker = time.NewTicker(chatrate)
}
case gotocol.GetResponse:
// return path from a request
// nothing to do at this level
case gotocol.Goodbye:
if archaius.Conf.Msglog {
log.Printf("%v: Going away, chatting every %v\n", name, chatrate)
}
gotocol.Message{gotocol.Goodbye, nil, time.Now(), name}.GoSend(netflixoss)
return
}
case <-chatTicker.C:
if len(microservices) > 0 {
// build index if needed
if len(microindex) != len(microservices) {
i := 0
for _, ch := range microservices {
microindex[i] = ch
i++
}
}
m := rand.Intn(len(microservices))
// start a request to a random member of this elb
gotocol.Message{gotocol.GetRequest, listener, time.Now(), name}.GoSend(microindex[m])
}
//default:
}
}
}