From b3fbd36ba7d2fe5de90896507794ee6a98311ecb Mon Sep 17 00:00:00 2001 From: Asim Date: Sat, 9 Apr 2016 21:30:31 +0100 Subject: [PATCH 1/3] Don't re-register if the state hasn't changed --- registry/consul_registry.go | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/registry/consul_registry.go b/registry/consul_registry.go index 0d2d67f1..76d93554 100644 --- a/registry/consul_registry.go +++ b/registry/consul_registry.go @@ -7,15 +7,20 @@ import ( "net" "net/http" "runtime" + "sync" "time" consul "github.com/hashicorp/consul/api" + hash "github.com/mitchellh/hashstructure" ) type consulRegistry struct { Address string Client *consul.Client Options Options + + sync.Mutex + register map[string]uint64 } func newTransport(config *tls.Config) *http.Transport { @@ -90,6 +95,11 @@ func (c *consulRegistry) Deregister(s *Service) error { return errors.New("Require at least one node") } + // delete our hash of the service + c.Lock() + delete(c.register, s.Name) + c.Unlock() + node := s.Nodes[0] return c.Client.Agent().ServiceDeregister(node.Id) } @@ -104,20 +114,44 @@ func (c *consulRegistry) Register(s *Service, opts ...RegisterOption) error { o(&options) } + // create hash of service; uint64 + h, err := hash.Hash(s, nil) + if err != nil { + return err + } + + // use first node node := s.Nodes[0] + // get existing hash + c.Lock() + v, ok := c.register[s.Name] + c.Unlock() + + // if it's already registered and matches then just pass the check + if ok && v == h { + // if the err is nil we're all good, bail out + // if not, we don't know what the state is, so full re-register + if err := c.Client.Agent().PassTTL("service:"+node.Id, ""); err == nil { + return nil + } + } + + // encode the tags tags := encodeMetadata(node.Metadata) tags = append(tags, encodeEndpoints(s.Endpoints)...) tags = append(tags, encodeVersion(s.Version)...) var check *consul.AgentServiceCheck + // if the TTL is greater than 0 create an associated check if options.TTL > time.Duration(0) { check = &consul.AgentServiceCheck{ TTL: fmt.Sprintf("%v", options.TTL), } } + // register the service if err := c.Client.Agent().ServiceRegister(&consul.AgentServiceRegistration{ ID: node.Id, Name: s.Name, @@ -129,10 +163,17 @@ func (c *consulRegistry) Register(s *Service, opts ...RegisterOption) error { return err } + // save our hash of the service + c.Lock() + c.register[s.Name] = h + c.Unlock() + + // if the TTL is 0 we don't mess with the checks if options.TTL == time.Duration(0) { return nil } + // pass the healthcheck return c.Client.Agent().PassTTL("service:"+node.Id, "") } From 9d7bd3f42426bfdde7065484829035b01ccc5428 Mon Sep 17 00:00:00 2001 From: Asim Date: Sat, 9 Apr 2016 21:34:45 +0100 Subject: [PATCH 2/3] God damn you nil map --- registry/consul_registry.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/registry/consul_registry.go b/registry/consul_registry.go index 76d93554..d95670db 100644 --- a/registry/consul_registry.go +++ b/registry/consul_registry.go @@ -82,9 +82,10 @@ func newConsulRegistry(opts ...Option) Registry { client, _ := consul.NewClient(config) cr := &consulRegistry{ - Address: config.Address, - Client: client, - Options: options, + Address: config.Address, + Client: client, + Options: options, + register: make(map[string]uint64), } return cr From e2855c4bc24493690e48de9f4115097215827f36 Mon Sep 17 00:00:00 2001 From: Asim Date: Sat, 9 Apr 2016 22:19:03 +0100 Subject: [PATCH 3/3] Fix some mapping issues while we're at it --- registry/consul_registry.go | 11 ++--------- registry/consul_watcher.go | 14 +++----------- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/registry/consul_registry.go b/registry/consul_registry.go index d95670db..e98edbf3 100644 --- a/registry/consul_registry.go +++ b/registry/consul_registry.go @@ -200,17 +200,10 @@ func (c *consulRegistry) GetService(name string) ([]*Service, error) { // address is service address address := s.Service.Address - // if we can't get the new type of version + // if we can't get the version we bail // use old the old ways if !found { - // id was set as node - id = s.Node.Node - // key was service id - key = s.Service.ID - // version was service id - version = s.Service.ID - // address was address - address = s.Node.Address + continue } svc, ok := serviceMap[key] diff --git a/registry/consul_watcher.go b/registry/consul_watcher.go index 0327f5af..8e1cb8e4 100644 --- a/registry/consul_watcher.go +++ b/registry/consul_watcher.go @@ -62,17 +62,9 @@ func (cw *consulWatcher) serviceHandler(idx uint64, data interface{}) { // address is service address address := e.Service.Address - // if we can't get the new type of version - // use old the old ways + // if we can't get the version we bail if !found { - // id was set as node - id = e.Node.Node - // key was service id - key = e.Service.ID - // version was service id - version = e.Service.ID - // address was address - address = e.Node.Address + continue } svc, ok := serviceMap[key] @@ -156,7 +148,7 @@ func (cw *consulWatcher) serviceHandler(idx uint64, data interface{}) { for _, old := range rservices[serviceName] { // old version does not exist in new version map // kill it with fire! - if _, ok := serviceMap[serviceName+old.Version]; !ok { + if _, ok := serviceMap[old.Version]; !ok { cw.next <- &Result{Action: "delete", Service: old} } }