Skip to content

Commit 1849eb4

Browse files
committed
Fixed eureka regenerated json
Fixed a deep bug where eureka wouldn’t namedrop more than one dependency. Sanity check for _arch.json files found bugs. Generated json for everything again including large scale
1 parent 840e751 commit 1849eb4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+433377
-107071
lines changed

Diff for: archaius/archaius.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ type Configuration struct {
3636
RegionNames [6]string `json:"regionnames,omitempty"`
3737

3838
// ZoneNames is the default names of the zones
39-
ZoneNames [3]string `json:"zonenames,omitempty"`
39+
ZoneNames [3]string `json:"zonenames,omitempty"`
4040

4141
// Collect turns on Metrics collection
4242
Collect bool `json:"collect,omitempty"`
@@ -50,7 +50,7 @@ type Configuration struct {
5050

5151
var Conf = Configuration{
5252
RegionNames: [...]string{"us-east-1", "us-west-2", "eu-west-1", "eu-east-1", "ap-south-1", "ap-south-2"},
53-
ZoneNames: [...]string{"zoneA", "zoneB", "zoneC"},
53+
ZoneNames: [...]string{"zoneA", "zoneB", "zoneC"},
5454
}
5555

5656
// return current config as json

Diff for: architecture/architecture.go

+32
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,41 @@ func ReadArch(arch string) *archV0r0 {
5757
a := new(archV0r0)
5858
e := json.Unmarshal(data, a)
5959
if e == nil {
60+
names := make(map[string]bool, 10)
61+
names[asgard.EurekaPkg] = true // special case to allow cross region references
62+
packs := make(map[string]bool, 10)
63+
for _, p := range asgard.Packages {
64+
packs[p] = true
65+
}
66+
// map all the service names and check packages exist
67+
for _, s := range a.Services {
68+
if names[s.Name] == true {
69+
log.Println(names)
70+
log.Println(s)
71+
log.Fatal("Duplicate service name in architecture: " + s.Name)
72+
} else {
73+
names[s.Name] = true
74+
}
75+
if packs[s.Package] != true {
76+
log.Println(packs)
77+
log.Println(s)
78+
log.Fatal("Unknown package name in architecture: " + s.Package)
79+
}
80+
}
81+
// check all the dependencies
82+
for _, s := range a.Services {
83+
for _, d := range s.Dependencies {
84+
if names[d] == false {
85+
log.Println(names)
86+
log.Println(s)
87+
log.Fatal("Unknown dependency name in architecture: " + d)
88+
}
89+
}
90+
}
6091
log.Printf("Architecture: %v %v\n", a.Arch, a.Description)
6192
return a
6293
} else {
94+
log.Fatal(e)
6395
return nil
6496
}
6597
}

Diff for: architecture/architecture_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ func TestGraph(t *testing.T) {
5454
//archaius.Conf.StopStep = 0
5555
archaius.Conf.EurekaPoll = "1s"
5656
try(testJSONarchV0r0)
57+
//ReadArch("testDuplicate") // these three are designed to fail, uncomment one at a time to check
58+
//ReadArch("testMissingDep")
59+
//ReadArch("testBadPackage")
5760
a := ReadArch("test")
5861
fmt.Println(a)
5962
Start(a)

Diff for: architecture/json_arch/testBadPackage_arch.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"arch":"test",
3+
"version":"arch-0.0",
4+
"args":"[spigo -j -d=0 -a netflixoss]",
5+
"description":"test structure",
6+
"victim":"homepage-node",
7+
"date":"2015-04-26T23:52:45.959905585+12:00",
8+
"services":[
9+
{ "name":"mysql", "package":"store", "regions":1, "count":2, "dependencies":[] },
10+
{ "name":"homepage-node", "package":"karyon", "regions":1, "count":9, "dependencies":["mysql"] },
11+
{ "name":"signup-node", "package":"unknown", "regions":1, "count":3, "dependencies":["mysql"] },
12+
{ "name":"www-proxy", "package":"zuul", "regions":1, "count":3, "dependencies":["signup-node", "homepage-node"] },
13+
{ "name":"www-elb", "package":"elb", "regions":1, "count":0, "dependencies":["www-proxy"] },
14+
{ "name":"www", "package":"denominator", "regions":0, "count":0, "dependencies":["www-elb"] }
15+
]
16+
}

Diff for: architecture/json_arch/testDuplicate_arch.json

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"arch":"test",
3+
"version":"arch-0.0",
4+
"args":"[spigo -j -d=0 -a netflixoss]",
5+
"description":"test structure",
6+
"victim":"homepage-node",
7+
"date":"2015-04-26T23:52:45.959905585+12:00",
8+
"services":[
9+
{ "name":"mysql", "package":"store", "regions":1, "count":2, "dependencies":[] },
10+
{ "name":"homepage-node", "package":"karyon", "regions":1, "count":9, "dependencies":["mysql"] },
11+
{ "name":"signup-node", "package":"karyon", "regions":1, "count":3, "dependencies":["mysql"] },
12+
{ "name":"signup-node", "package":"karyon", "regions":1, "count":3, "dependencies":["mysql"] },
13+
{ "name":"www-proxy", "package":"zuul", "regions":1, "count":3, "dependencies":["signup-node", "homepage-node"] },
14+
{ "name":"www-elb", "package":"elb", "regions":1, "count":0, "dependencies":["www-proxy"] },
15+
{ "name":"www", "package":"denominator", "regions":0, "count":0, "dependencies":["www-elb"] }
16+
]
17+
}

Diff for: architecture/json_arch/testMissingDep_arch.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"arch":"test",
3+
"version":"arch-0.0",
4+
"args":"[spigo -j -d=0 -a netflixoss]",
5+
"description":"test structure",
6+
"victim":"homepage-node",
7+
"date":"2015-04-26T23:52:45.959905585+12:00",
8+
"services":[
9+
{ "name":"mysql", "package":"store", "regions":1, "count":2, "dependencies":[] },
10+
{ "name":"homepage-node", "package":"karyon", "regions":1, "count":9, "dependencies":["mysql"] },
11+
{ "name":"signup-node", "package":"karyon", "regions":1, "count":3, "dependencies":["mysql"] },
12+
{ "name":"www-proxy", "package":"zuul", "regions":1, "count":3, "dependencies":["signup-node", "homepage-node", "missing"] },
13+
{ "name":"www-elb", "package":"elb", "regions":1, "count":0, "dependencies":["www-proxy"] },
14+
{ "name":"www", "package":"denominator", "regions":0, "count":0, "dependencies":["www-elb"] }
15+
]
16+
}

Diff for: asgard/asgard.go

+15-10
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,13 @@ var (
4040
listener chan gotocol.Message // asgard listener
4141
eurekachan map[string]chan gotocol.Message // eureka for each region and zone
4242
// noodles channels mapped by microservice name connects netflixoss to everyone
43-
noodles map[string]chan gotocol.Message
43+
noodles map[string]chan gotocol.Message
44+
Packages = []string{EurekaPkg, PiratePkg, ElbPkg, DenominatorPkg, ZuulPkg, KaryonPkg, MonolithPkg, StaashPkg, PriamCassandraPkg, StorePkg}
4445
)
4546

4647
// Create the maps of channels
4748
func CreateChannels() {
48-
listener = make(chan gotocol.Message) // listener for netflixoss
49+
listener = make(chan gotocol.Message) // listener for architecture
4950
noodles = make(map[string]chan gotocol.Message, archaius.Conf.Population)
5051
eurekachan = make(map[string]chan gotocol.Message, 3*archaius.Conf.Regions)
5152
}
@@ -59,18 +60,19 @@ func Create(servicename, packagename string, regions, count int, dependencies ..
5960
if regions == 0 { // for dns that isn't in a region or zone
6061
//log.Printf("Create cross region: " + servicename)
6162
name = names.Make(arch, "*", "*", servicename, packagename, 0)
62-
StartNode(name, dependencies)
63+
StartNode(name, dependencies...)
6364
}
6465
for r := 0; r < regions; r++ {
65-
if count == 0 { // for AWS services that are cross zone like elb
66+
if count == 0 { // for AWS services that are cross zone like elb and S3
6667
//log.Printf("Create cross zone: " + servicename)
6768
name = names.Make(arch, rnames[r], "*", servicename, packagename, 0)
68-
StartNode(name, dependencies)
69+
StartNode(name, dependencies...)
6970
} else {
7071
//log.Printf("Create service: " + servicename)
7172
for i := r * count; i < (r+1)*count; i++ {
7273
name = names.Make(arch, rnames[r], znames[i%3], servicename, packagename, i)
73-
StartNode(name, dependencies)
74+
//log.Println(dependencies)
75+
StartNode(name, dependencies...)
7476
}
7577
}
7678
}
@@ -95,7 +97,7 @@ func Reload(arch string) string {
9597
for _, element := range g.Graph {
9698
if element.Node != "" {
9799
name := element.Node
98-
StartNode(name, nil)
100+
StartNode(name, "")
99101
if names.Package(name) == DenominatorPkg {
100102
root = name
101103
}
@@ -134,7 +136,7 @@ func SendToName(name string, msg gotocol.Message) {
134136
}
135137

136138
// Start a node using the named package, and connect it to any dependencies
137-
func StartNode(name string, dependencies []string) {
139+
func StartNode(name string, dependencies ...string) {
138140
if names.Package(name) == "eureka" {
139141
eurekachan[name] = make(chan gotocol.Message, archaius.Conf.Population)
140142
go eureka.Start(eurekachan[name], name)
@@ -169,6 +171,7 @@ func StartNode(name string, dependencies []string) {
169171
// there is a eureka service registry in each zone, so in-zone services just get to talk to their local registry
170172
// elb are cross zone, so need to see all registries in a region
171173
// denominator are cross region so need to see all registries globally
174+
// priamCassandra depends explicitly on eureka for cross region clusters
172175
crossregion := false
173176
for _, d := range dependencies {
174177
if d == "eureka" {
@@ -191,9 +194,11 @@ func StartNode(name string, dependencies []string) {
191194
}
192195
}
193196
}
197+
//log.Println(dependencies)
194198
// pass on symbolic dependencies without channels that will be looked up in Eureka later
195199
for _, dep := range dependencies {
196200
if dep != "" && dep != "eureka" { // ignore special case of eureka in dependency list
201+
//log.Println(name + " depends on " + dep)
197202
gotocol.Send(noodles[name], gotocol.Message{gotocol.NameDrop, nil, time.Now(), dep})
198203
}
199204
}
@@ -241,9 +246,9 @@ func Run(rootservice, victim string) {
241246
SendToName(rootservice, gotocol.Message{gotocol.Chat, nil, time.Now(), delay})
242247
// wait until the delay has finished
243248
if archaius.Conf.RunDuration >= time.Millisecond {
244-
time.Sleep(archaius.Conf.RunDuration/2)
249+
time.Sleep(archaius.Conf.RunDuration / 2)
245250
chaosmonkey.Delete(&noodles, victim) // kill a random victim half way through
246-
time.Sleep(archaius.Conf.RunDuration/2)
251+
time.Sleep(archaius.Conf.RunDuration / 2)
247252
}
248253
log.Println("asgard: Shutdown")
249254
ShutdownNodes()

Diff for: denominator/denominator.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ func Start(listener chan gotocol.Message) {
1717
// remember the channel to talk to microservices
1818
microservices := make(map[string]chan gotocol.Message, dunbar)
1919
microindex := make([]chan gotocol.Message, dunbar)
20-
dependencies := make(map[string]time.Time, dunbar) // dependent services and time last updated
21-
var netflixoss chan gotocol.Message // remember how to talk back to creator
22-
var name string // remember my name
23-
hist := collect.NewHist("") // don't know name yet
24-
eureka := make(map[string]chan gotocol.Message, 3 * archaius.Conf.Regions) // service registry per zone and region
20+
dependencies := make(map[string]time.Time, dunbar) // dependent services and time last updated
21+
var netflixoss chan gotocol.Message // remember how to talk back to creator
22+
var name string // remember my name
23+
hist := collect.NewHist("") // don't know name yet
24+
eureka := make(map[string]chan gotocol.Message, 3*archaius.Conf.Regions) // service registry per zone and region
2525
var chatrate time.Duration
2626
ep, _ := time.ParseDuration(archaius.Conf.EurekaPoll)
2727
eurekaTicker := time.NewTicker(ep)

Diff for: eureka/eureka.go

+17-9
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,21 @@ import (
1515

1616
var Wg sync.WaitGroup
1717

18+
// metadata about a registered service
1819
type meta struct {
1920
online bool
2021
registered time.Time
2122
}
2223

24+
// interest in a specific service
25+
type callback struct {
26+
lookup string
27+
who chan gotocol.Message
28+
}
29+
2330
// Start eureka discovery service and set name directly
2431
func Start(listener chan gotocol.Message, name string) {
25-
// use a waitgroup so whoever starts eureka can tell the logs have been flushed
32+
// use a waitgroup so whoever starts eureka can tell it's ready and when stopping that the logs have been flushed
2633
Wg.Add(1)
2734
defer Wg.Done()
2835
var msg gotocol.Message
@@ -31,7 +38,7 @@ func Start(listener chan gotocol.Message, name string) {
3138
microservices := make(map[string]chan gotocol.Message, archaius.Conf.Dunbar)
3239
eurekaservices := make(map[string]chan gotocol.Message, 2)
3340
metadata := make(map[string]meta, archaius.Conf.Dunbar)
34-
lastrequest := make(map[chan gotocol.Message]time.Time) // remember time of last request from this requestor
41+
lastrequest := make(map[callback]time.Time) // remember time of last request for a service from this requestor
3542
log.Println(name + ": starting")
3643
for {
3744
msg, ok = <-listener
@@ -53,9 +60,9 @@ func Start(listener chan gotocol.Message, name string) {
5360
if microservices[msg.Intention] == nil { // ignore duplicate requests
5461
microservices[msg.Intention] = msg.ResponseChan
5562
metadata[msg.Intention] = meta{true, msg.Sent}
56-
// replicate request
63+
// replicate request, everyone ends up with the same timestamp for state change of this service
5764
for _, c := range eurekaservices {
58-
gotocol.Message{gotocol.Replicate, msg.ResponseChan, time.Now(), msg.Intention}.GoSend(c)
65+
gotocol.Message{gotocol.Replicate, msg.ResponseChan, msg.Sent, msg.Intention}.GoSend(c)
5966
}
6067
if edda.Logchan != nil {
6168
edda.Logchan <- msg
@@ -64,7 +71,7 @@ func Start(listener chan gotocol.Message, name string) {
6471
case gotocol.Replicate:
6572
if microservices[msg.Intention] == nil { // ignore multiple requests
6673
microservices[msg.Intention] = msg.ResponseChan
67-
metadata[msg.Intention] = meta{true, time.Now()}
74+
metadata[msg.Intention] = meta{true, msg.Sent}
6875
}
6976
case gotocol.Inform:
7077
// don't store edges in discovery but do log them
@@ -80,20 +87,21 @@ func Start(listener chan gotocol.Message, name string) {
8087
break
8188
}
8289
for n, ch := range microservices { // respond with all the online names that match the service component
83-
// log.Printf("%v: matching %v with %v\n", name, n, msg.Intention)
8490
if names.Service(n) == msg.Intention {
8591
// if there was an update for the looked up service since last check
86-
if metadata[n].registered.After(lastrequest[msg.ResponseChan]) {
92+
// log.Printf("%v: matching %v with %v, last: %v metadata: %v\n", name, n, msg.Intention, lastrequest[callback{n, msg.ResponseChan}], metadata[n].registered)
93+
if metadata[n].registered.After(lastrequest[callback{n, msg.ResponseChan}]) {
8794
if metadata[n].online {
8895
gotocol.Message{gotocol.NameDrop, ch, time.Now(), n}.GoSend(msg.ResponseChan)
8996
} else {
97+
log.Printf("%v:Forget %v\n", name, n)
9098
gotocol.Message{gotocol.Forget, ch, time.Now(), n}.GoSend(msg.ResponseChan)
9199
}
92100
}
101+
// remember for next time
102+
lastrequest[callback{n, msg.ResponseChan}] = msg.Sent
93103
}
94104
}
95-
// remember for next time
96-
lastrequest[msg.ResponseChan] = time.Now()
97105
case gotocol.Delete: // remove a node
98106
if microservices[msg.Intention] != nil { // matched a unique full name
99107
metadata[msg.Intention] = meta{false, time.Now()}

Diff for: gotocol/gotocol.go

+1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ func NameDropHandler(dependencies *map[string]time.Time, microservices *map[stri
114114
if msg.ResponseChan == nil { // dependency by service name, needs to be looked up in eureka
115115
(*dependencies)[msg.Intention] = msg.Sent // remember it for later
116116
for _, ch := range eureka {
117+
//log.Println(name + " looking up " + msg.Intention)
117118
Send(ch, Message{GetRequest, listener, time.Now(), msg.Intention})
118119
}
119120
} else { // update dependency with full name and listener channel

0 commit comments

Comments
 (0)