예제 #1
0
파일: cache.go 프로젝트: ZhuJingfa/go-micro
// cp copies a service. Because we're caching handing back pointers would
// create a race condition, so we do this instead
// its fast enough
func (c *cacheSelector) cp(current []*registry.Service) []*registry.Service {
	var services []*registry.Service

	for _, service := range current {
		// copy service
		s := new(registry.Service)
		*s = *service

		// copy nodes
		var nodes []*registry.Node
		for _, node := range service.Nodes {
			n := new(registry.Node)
			*n = *node
			nodes = append(nodes, n)
		}
		s.Nodes = nodes

		// copy endpoints
		var eps []*registry.Endpoint
		for _, ep := range service.Endpoints {
			e := new(registry.Endpoint)
			*e = *ep
			eps = append(eps, e)
		}
		s.Endpoints = eps

		// append service
		services = append(services, s)
	}

	return services
}
예제 #2
0
// FilterLabel is a label based Select Filter which will
// only return services with the label specified.
func FilterLabel(key, val string) Filter {
	return func(old []*registry.Service) []*registry.Service {
		var services []*registry.Service

		for _, service := range old {
			serv := new(registry.Service)
			var nodes []*registry.Node

			for _, node := range service.Nodes {
				if node.Metadata == nil {
					continue
				}

				if node.Metadata[key] == val {
					nodes = append(nodes, node)
				}
			}

			// only add service if there's some nodes
			if len(nodes) > 0 {
				// copy
				*serv = *service
				serv.Nodes = nodes
				services = append(services, serv)
			}
		}

		return services
	}
}
예제 #3
0
파일: label.go 프로젝트: micro/router-srv
func Apply(labels []*label.LabelSet, s *registry.Service) {
	// sort low to high
	sortedLabels := Labels(labels)

	sort.Sort(sortedLabels)

	for _, label := range sortedLabels {
		// does the label have a version and does it match?
		if len(label.Version) > 0 && label.Version != s.Version {
			continue
		}

		// ok so either the version matches or its a generic apply

		// delete they label
		if label.Weight == 0 {
			v := s.Metadata[label.Key]
			// if there's a key value and its the same
			// or if the key value is blank
			if i := len(label.Value); i > 0 && v == label.Value || i == 0 {
				delete(s.Metadata, label.Key)
			}

			// delete from the nodes
			for _, node := range s.Nodes {
				v := node.Metadata[label.Key]
				if i := len(label.Value); i > 0 && v == label.Value || i == 0 {
					delete(node.Metadata, label.Key)
				}
			}
			// other weight is greater than 0, create label
		} else {
			// Apply at the top level
			// Should we actually apply as a sampling here?
			// Or at the individual node basis?
			if label.Weight == 100 {
				if s.Metadata == nil {
					s.Metadata = make(map[string]string)
				}
				s.Metadata[label.Key] = label.Value
			}

			// Apply to nodes
			for _, node := range s.Nodes {
				// Apply based on the weight
				if rand.Int63n(100) <= label.Weight {
					if node.Metadata == nil {
						node.Metadata = make(map[string]string)
					}
					node.Metadata[label.Key] = label.Value
				}
			}
		}
	}
}
예제 #4
0
파일: filter.go 프로젝트: micro/go-plugins
func (r *blacklist) Filter(services []*registry.Service) ([]*registry.Service, error) {
	var viableServices []*registry.Service

	r.RLock()

	for _, service := range services {
		var viableNodes []*registry.Node

		for _, node := range service.Nodes {
			n, ok := r.bl[node.Id]
			if !ok {
				// blacklist miss so add it
				viableNodes = append(viableNodes, node)
				continue
			}

			// got some blacklist info
			// skip the node if it exceeds count
			if n.count >= count {
				continue
			}

			// doesn't exceed count, still viable
			viableNodes = append(viableNodes, node)
		}

		if len(viableNodes) == 0 {
			continue
		}

		viableService := new(registry.Service)
		*viableService = *service
		viableService.Nodes = viableNodes
		viableServices = append(viableServices, viableService)
	}

	r.RUnlock()

	return viableServices, nil
}
예제 #5
0
// registers a service against a given pod
func register(r registry.Registry, podName string, svc *registry.Service) {
	os.Setenv("HOSTNAME", podName)

	pod := setupPod(podName)

	svc.Nodes = append(svc.Nodes, &registry.Node{
		Id:       svc.Name + ":" + pod.Metadata.Name,
		Address:  pod.Status.PodIP,
		Port:     80,
		Metadata: map[string]string{},
	})

	if err := r.Register(svc); err != nil {
		log.Fatalf("did not expect Register() to fail: %v", err)
	}

	os.Setenv("HOSTNAME", "")
}
예제 #6
0
파일: cache.go 프로젝트: ZhuJingfa/go-micro
func (c *cacheSelector) update(res *registry.Result) {
	if res == nil || res.Service == nil {
		return
	}

	c.Lock()
	defer c.Unlock()

	services, ok := c.cache[res.Service.Name]
	if !ok {
		// we're not going to cache anything
		// unless there was already a lookup
		return
	}

	if len(res.Service.Nodes) == 0 {
		switch res.Action {
		case "delete":
			c.del(res.Service.Name)
		}
		return
	}

	// existing service found
	var service *registry.Service
	var index int
	for i, s := range services {
		if s.Version == res.Service.Version {
			service = s
			index = i
		}
	}

	switch res.Action {
	case "create", "update":
		if service == nil {
			c.set(res.Service.Name, append(services, res.Service))
			return
		}

		// append old nodes to new service
		for _, cur := range service.Nodes {
			var seen bool
			for _, node := range res.Service.Nodes {
				if cur.Id == node.Id {
					seen = true
					break
				}
			}
			if !seen {
				res.Service.Nodes = append(res.Service.Nodes, cur)
			}
		}

		services[index] = res.Service
		c.set(res.Service.Name, services)
	case "delete":
		if service == nil {
			return
		}

		var nodes []*registry.Node

		// filter cur nodes to remove the dead one
		for _, cur := range service.Nodes {
			var seen bool
			for _, del := range res.Service.Nodes {
				if del.Id == cur.Id {
					seen = true
					break
				}
			}
			if !seen {
				nodes = append(nodes, cur)
			}
		}

		// still got nodes, save and return
		if len(nodes) > 0 {
			service.Nodes = nodes
			services[index] = service
			c.set(service.Name, services)
			return
		}

		// zero nodes left

		// only have one thing to delete
		// nuke the thing
		if len(services) == 1 {
			c.del(service.Name)
			return
		}

		// still have more than 1 service
		// check the version and keep what we know
		var srvs []*registry.Service
		for _, s := range services {
			if s.Version != service.Version {
				srvs = append(srvs, s)
			}
		}

		// save
		c.set(service.Name, srvs)
	}
}
예제 #7
0
파일: os.go 프로젝트: micro/go-platform
func (o *os) update(res *registry.Result) {
	if res == nil || res.Service == nil {
		return
	}

	o.Lock()
	defer o.Unlock()

	services, ok := o.cache[res.Service.Name]
	if !ok {
		// we're not going to cache anything
		// unless there was already a lookup
		return
	}

	if len(res.Service.Nodes) == 0 {
		switch res.Action {
		case "delete":
			delete(o.cache, res.Service.Name)
		}
		return
	}

	// existing service found
	var service *registry.Service
	var index int
	for i, s := range services {
		if s.Version == res.Service.Version {
			service = s
			index = i
		}
	}

	switch res.Action {
	case "create", "update":
		if service == nil {
			services = append(services, res.Service)
			o.cache[res.Service.Name] = services
			return
		}

		// append old nodes to new service
		for _, cur := range service.Nodes {
			var seen bool
			for _, node := range res.Service.Nodes {
				if cur.Id == node.Id {
					seen = true
					break
				}
			}
			if !seen {
				res.Service.Nodes = append(res.Service.Nodes, cur)
			}
		}

		services[index] = res.Service
		o.cache[res.Service.Name] = services
	case "delete":
		if service == nil {
			return
		}

		var nodes []*registry.Node

		// filter cur nodes to remove the dead one
		for _, cur := range service.Nodes {
			var seen bool
			for _, del := range res.Service.Nodes {
				if del.Id == cur.Id {
					seen = true
					break
				}
			}
			if !seen {
				nodes = append(nodes, cur)
			}
		}

		if len(nodes) == 0 {
			if len(services) == 1 {
				delete(o.cache, service.Name)
			} else {
				var srvs []*registry.Service
				for _, s := range services {
					if s.Version != service.Version {
						srvs = append(srvs, s)
					}
				}
				o.cache[service.Name] = srvs
			}
			return
		}

		service.Nodes = nodes
		services[index] = service
		o.cache[res.Service.Name] = services
	}
}