Пример #1
0
// ForgetHandler removes a buddy from the buddy list
func ForgetHandler(dependencies *map[string]time.Time, microservices *map[string]chan Message, msg Message) {
	microservice := msg.Intention              // message body is buddy name to forget
	if (*microservices)[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
		delete(*microservices, microservice)
	}
}
Пример #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.NewRequest(), "chaosmonkey"}.GoSend(ch)
				log.Println("chaosmonkey delete: " + node)
				return
			}
		}
	}
}
Пример #3
0
func NameDropHandler(dependencies *map[string]time.Time, microservices *map[string]chan Message, msg Message, name string, listener chan Message, eureka map[string]chan 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)
			Send(ch, Message{GetRequest, listener, time.Now(), 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 && (*microservices)[microservice] == nil { // don't talk to myself or record duplicates
				// remember how to talk to this buddy
				(*microservices)[microservice] = msg.ResponseChan // message channel is buddy's listener
				(*dependencies)[names.Service(microservice)] = msg.Sent
				for _, ch := range eureka {
					// tell one of the service registries I have a new buddy to talk to so it doesn't get logged more than once
					Send(ch, Message{Inform, listener, time.Now(), NilContext, name + " " + microservice})
					return
				}
			}
		}
	}
}
Пример #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
		}
		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, 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(), 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(), n}.GoSend(msg.ResponseChan)
						} else {
							log.Printf("%v:Forget %v\n", name, n)
							gotocol.Message{gotocol.Forget, ch, time.Now(), 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(), msg.Intention}.GoSend(c)
				}
				if edda.Logchan != nil {
					edda.Logchan <- msg
				}
			}
		case gotocol.Goodbye:
			gotocol.Message{gotocol.Goodbye, nil, time.Now(), name}.GoSend(msg.ResponseChan)
			log.Println(name + ": closing")
			return
		}
	}
}