Esempio n. 1
0
// Forget removes a buddy from the buddy list
func Forget(dependencies *map[string]time.Time, router *ribbon.Router, msg gotocol.Message) {
	microservice := msg.Intention          // message body is buddy name to forget
	if router.Named(microservice) != nil { // an existing buddy to forget
		// forget how to talk to this buddy
		(*dependencies)[names.Service(microservice)] = msg.Sent // remember when we were told to forget this service
		router.Remove(microservice)
	}
}
Esempio n. 2
0
// Delete a single node from the given service
func Delete(noodles *map[string]chan gotocol.Message, service string) {
	if service != "" {
		for node, ch := range *noodles {
			if names.Service(node) == service {
				gotocol.Message{gotocol.Goodbye, nil, time.Now(), gotocol.NewTrace(), "chaosmonkey"}.GoSend(ch)
				log.Println("chaosmonkey delete: " + node)
				return
			}
		}
	}
}
Esempio n. 3
0
// NameDrop updates local buddy list
func NameDrop(dependencies *map[string]time.Time, router *ribbon.Router, msg gotocol.Message, name string, listener chan gotocol.Message, eureka map[string]chan gotocol.Message, crosszone ...bool) {
	if msg.ResponseChan == nil { // dependency by service name, needs to be looked up in eureka
		(*dependencies)[msg.Intention] = msg.Sent // remember it for later
		for _, ch := range eureka {
			//log.Println(name + " looking up " + msg.Intention)
			gotocol.Send(ch, gotocol.Message{gotocol.GetRequest, listener, time.Now(), gotocol.NilContext, msg.Intention})
		}
	} else { // update dependency with full name and listener channel
		microservice := msg.Intention // message body is buddy name
		if len(crosszone) > 0 || names.Zone(name) == names.Zone(microservice) {
			if microservice != name && router.Named(microservice) == nil { // don't talk to myself or record duplicates
				// remember how to talk to this buddy
				router.Add(microservice, msg.ResponseChan, msg.Sent) // message channel is buddy's listener
				(*dependencies)[names.Service(microservice)] = msg.Sent
				for _, ch := range eureka {
					// tell just one of the service registries I have a new buddy to talk to so it doesn't get logged more than once
					gotocol.Send(ch, gotocol.Message{gotocol.Inform, listener, time.Now(), gotocol.NilContext, name + " " + microservice})
					return
				}
			}
		}
	}
}
Esempio n. 4
0
// Start eureka discovery service and set name directly
func Start(listener chan gotocol.Message, name string) {
	// use a waitgroup so whoever starts eureka can tell it's ready and when stopping that the logs have been flushed
	Wg.Add(1)
	defer Wg.Done()
	var msg gotocol.Message
	var ok bool
	hist := collect.NewHist(name)
	microservices := make(map[string]chan gotocol.Message, archaius.Conf.Dunbar)
	eurekaservices := make(map[string]chan gotocol.Message, 2)
	metadata := make(map[string]meta, archaius.Conf.Dunbar)
	lastrequest := make(map[callback]time.Time) // remember time of last request for a service from this requestor
	log.Println(name + ": starting")
	for {
		msg, ok = <-listener
		collect.Measure(hist, time.Since(msg.Sent))
		if !ok {
			break // channel was closed
		}
		//commented out because name service traffic is too much noise in the log
		//if archaius.Conf.Msglog {
		//	log.Printf("%v(backlog %v): %v\n", name, len(listener), msg)
		//}
		switch msg.Imposition {
		// used to wire up connections to other eureka nodes only
		case gotocol.NameDrop:
			if msg.Intention != name { // don't talk to myself
				eurekaservices[msg.Intention] = msg.ResponseChan
			}
		// for new nodes record the data, replicate and maybe pass on to be logged
		case gotocol.Put:
			if microservices[msg.Intention] == nil { // ignore duplicate requests
				microservices[msg.Intention] = msg.ResponseChan
				metadata[msg.Intention] = meta{true, msg.Sent}
				// replicate request, everyone ends up with the same timestamp for state change of this service
				for _, c := range eurekaservices {
					gotocol.Message{gotocol.Replicate, msg.ResponseChan, msg.Sent, gotocol.NilContext, msg.Intention}.GoSend(c)
				}
				if edda.Logchan != nil {
					edda.Logchan <- msg
				}
			}
		case gotocol.Replicate:
			if microservices[msg.Intention] == nil { // ignore multiple requests
				microservices[msg.Intention] = msg.ResponseChan
				metadata[msg.Intention] = meta{true, msg.Sent}
			}
		case gotocol.Inform:
			// don't store edges in discovery but do log them
			if edda.Logchan != nil {
				edda.Logchan <- msg
			}
		case gotocol.GetRequest:
			if msg.Intention == "" {
				log.Fatal(name + ": empty GetRequest")
			}
			if microservices[msg.Intention] != nil { // matched a unique full name
				gotocol.Message{gotocol.NameDrop, microservices[msg.Intention], time.Now(), gotocol.NilContext, msg.Intention}.GoSend(msg.ResponseChan)
				break
			}
			for n, ch := range microservices { // respond with all the online names that match the service component
				if names.Service(n) == msg.Intention {
					// if there was an update for the looked up service since last check
					// log.Printf("%v: matching %v with %v, last: %v metadata: %v\n", name, n, msg.Intention, lastrequest[callback{n, msg.ResponseChan}], metadata[n].registered)
					if metadata[n].registered.After(lastrequest[callback{n, msg.ResponseChan}]) {
						if metadata[n].online {
							gotocol.Message{gotocol.NameDrop, ch, time.Now(), gotocol.NilContext, n}.GoSend(msg.ResponseChan)
						} else {
							//log.Printf("%v:Forget %v\n", name, n)
							gotocol.Message{gotocol.Forget, ch, time.Now(), gotocol.NilContext, n}.GoSend(msg.ResponseChan)
						}
					}
					// remember for next time
					lastrequest[callback{n, msg.ResponseChan}] = msg.Sent
				}
			}
		case gotocol.Delete: // remove a node
			if microservices[msg.Intention] != nil { // matched a unique full name
				metadata[msg.Intention] = meta{false, time.Now()}
				// replicate request
				for _, c := range eurekaservices {
					gotocol.Message{gotocol.Replicate, nil, time.Now(), gotocol.NilContext, msg.Intention}.GoSend(c)
				}
				if edda.Logchan != nil {
					edda.Logchan <- msg
				}
			}
		case gotocol.Goodbye:
			gotocol.Message{gotocol.Goodbye, nil, time.Now(), gotocol.NilContext, name}.GoSend(msg.ResponseChan)
			log.Println(name + ": closing")
			return
		}
	}
}
Esempio n. 5
0
// record messages in neo4j as well as zipkin
func WriteFlow(source, target, call string, tnano int64, trace gotocol.TraceContextType) {
	if Enabled == false {
		return
	}
	if epoch == 0 {
		epoch = tnano
	}
	Write(fmt.Sprintf("MATCH (from:%v {name: %q}), (to:%v {name: %q})\nCREATE (from)-[:%v {arch:%q, timenano:%v, trace:%v}]->(to)", names.Service(source), names.Instance(source), names.Service(target), names.Instance(target), call, archaius.Conf.Arch+ss, tnano-epoch, trace))
}
Esempio n. 6
0
// WriteEdge writes the edge to a file given a space separated from and to node name
func WriteEdge(fromTo string, t time.Time) {
	if Enabled == false {
		return
	}
	var source, target string
	fmt.Sscanf(fromTo, "%s%s", &source, &target) // two space delimited names
	tstamp := t.Format(time.RFC3339Nano)
	Write(fmt.Sprintf("MATCH (from:%v {name: %q}), (to:%v {name: %q})\nCREATE (from)-[:CONN {arch:%q, timestamp:%q}]->(to)", names.Service(source), names.Instance(source), names.Service(target), names.Instance(target), archaius.Conf.Arch+ss, tstamp))
}
Esempio n. 7
0
// WriteNode writes the node to a file given a space separated name and service type
func WriteNode(nameService string, t time.Time) {
	if Enabled == false {
		return
	}
	var node, pack string
	fmt.Sscanf(nameService, "%s%s", &node, &pack) // space delimited
	tstamp := t.Format(time.RFC3339Nano)
	// node id should be unique and package indicates service type
	nodestmt, err := db.Prepare(fmt.Sprintf("CREATE (:%v:%v:%v {name:{0}, node:{1}, timestamp:{2}, ip:{3}, region:{4}, zone:{5}})", archaius.Conf.Arch+ss, pack, names.Service(node)))
	if err != nil {
		log.Fatal(err)
	}
	_, err = nodestmt.Exec(names.Instance(node), node, tstamp, dhcp.Lookup(node), names.Region(node), names.Zone(node))
	if err != nil {
		log.Fatal(err)
	}
	nodestmt.Close()
}