From 1a23b4accfcebef53480026365145db7e277c816 Mon Sep 17 00:00:00 2001 From: Dan Fuhry Date: Fri, 21 Mar 2025 22:49:08 -0400 Subject: [PATCH] [sd] differentiate node name and shard name Shard is not always applicable to sd entries, but sd entries do need some kind of discriminator for etcd path collision avoidance. Use the first element of the hostname for collision avoidance, and make shard an optional element that nests items one level deeper. --- sd/healthcheck.go | 1 + sd/healthcheck_http.go | 6 +++++- sd/healthcheck_ldap.go | 6 +++++- sd/publish.go | 32 ++++++++++++++++++++++++-------- sd/watcher.go | 7 +++++++ 5 files changed, 42 insertions(+), 10 deletions(-) diff --git a/sd/healthcheck.go b/sd/healthcheck.go index fd87d10..89163a3 100644 --- a/sd/healthcheck.go +++ b/sd/healthcheck.go @@ -54,6 +54,7 @@ type HealthStatus uint type ServiceDefinition struct { Engine string `json:"type"` ServiceName string `json:"service_name"` + Shard string `json:"shard"` PollInterval uint `json:"poll_interval"` } diff --git a/sd/healthcheck_http.go b/sd/healthcheck_http.go index 00a54d9..773af2b 100644 --- a/sd/healthcheck_http.go +++ b/sd/healthcheck_http.go @@ -63,6 +63,10 @@ func (hcs *httpHealthCheckService) ServiceDefinition() *ServiceDefinition { func (hcs *httpHealthCheckService) NewPublisher(domain string, regions []string) *SDPublisher { _, port := hcs.PublishAddress() + shard := hcs.serviceDef.Shard + if shard == "" { + shard = strings.Split(hcs.SocketHost, ".")[0] + } publisher := &SDPublisher{ AdvertiseHost: hcs.SocketHost, @@ -70,7 +74,7 @@ func (hcs *httpHealthCheckService) NewPublisher(domain string, regions []string) Domain: domain, Protocol: ProtocolTCP, Service: hcs.serviceDef.ServiceName, - ShardName: strings.Split(hcs.SocketHost, ".")[0], + ShardName: shard, Regions: regions, } diff --git a/sd/healthcheck_ldap.go b/sd/healthcheck_ldap.go index 5b54ae0..cc00084 100644 --- a/sd/healthcheck_ldap.go +++ b/sd/healthcheck_ldap.go @@ -58,6 +58,10 @@ func (lcs *ldapHealthCheckService) ServiceDefinition() *ServiceDefinition { func (lcs *ldapHealthCheckService) NewPublisher(domain string, regions []string) *SDPublisher { _, port := lcs.PublishAddress() + shard := lcs.serviceDef.Shard + if shard == "" { + shard = strings.Split(lcs.SocketHost, ".")[0] + } publisher := &SDPublisher{ AdvertiseHost: lcs.SocketHost, @@ -65,7 +69,7 @@ func (lcs *ldapHealthCheckService) NewPublisher(domain string, regions []string) Domain: domain, Protocol: ProtocolTCP, Service: lcs.serviceDef.ServiceName, - ShardName: strings.Split(lcs.SocketHost, ".")[0], + ShardName: shard, Regions: regions, } diff --git a/sd/publish.go b/sd/publish.go index 02f01d1..abe5c5b 100644 --- a/sd/publish.go +++ b/sd/publish.go @@ -28,6 +28,7 @@ type SDPublisher struct { Domain string Protocol Layer4Protocol Service string + NodeName string ShardName string LocalRegion string Regions []string @@ -100,8 +101,8 @@ func (s *SDPublisher) init() error { errors = append(errors, "service name was not set") } - if s.ShardName == "" { - s.ShardName = hostname.Hostname() + if s.NodeName == "" { + s.NodeName = hostname.Hostname() } if s.LocalRegion == "" { @@ -291,12 +292,17 @@ func (s *SDPublisher) renewalTick() { func (s *SDPublisher) srvRecordPath() string { domainPathComponents := strings.Join(utils.Reverse(strings.Split(s.Domain, ".")), "/") - return fmt.Sprintf("/sd/%s/%s/%s/_%s/%s", + shardName := "" + if s.ShardName != "" { + shardName = "/" + s.ShardName + } + return fmt.Sprintf("/sd/%s/%s/%s/_%s/%s%s", "dns", domainPathComponents, s.Protocol.DNSComponent(), s.Service, - s.ShardName) + s.NodeName, + shardName) } func (s *SDPublisher) srvRecordJson(region string) string { @@ -316,11 +322,16 @@ func (s *SDPublisher) srvRecordJson(region string) string { func (s *SDPublisher) aRecordPath() string { domainPathComponents := strings.Join(utils.Reverse(strings.Split(s.Domain, ".")), "/") - return fmt.Sprintf("/sd/%s/%s/%s/%s/a", + shardName := "" + if s.ShardName != "" { + shardName = "/" + s.ShardName + } + return fmt.Sprintf("/sd/%s/%s/%s/%s%s/a", "dns", domainPathComponents, s.Service, - s.ShardName) + s.NodeName, + shardName) } func (s *SDPublisher) aRecordJson() string { @@ -334,11 +345,16 @@ func (s *SDPublisher) aRecordJson() string { func (s *SDPublisher) aaaaRecordPath() string { domainPathComponents := strings.Join(utils.Reverse(strings.Split(s.Domain, ".")), "/") - return fmt.Sprintf("/sd/%s/%s/%s/%s/aaaa", + shardName := "" + if s.ShardName != "" { + shardName = "/" + s.ShardName + } + return fmt.Sprintf("/sd/%s/%s/%s/%s%s/aaaa", "dns", domainPathComponents, s.Service, - s.ShardName) + s.NodeName, + shardName) } func (s *SDPublisher) aaaaRecordJson() string { diff --git a/sd/watcher.go b/sd/watcher.go index 8eca2e9..5d95d17 100644 --- a/sd/watcher.go +++ b/sd/watcher.go @@ -39,6 +39,7 @@ type ServiceAddress struct { IP6 string Protocol Layer4Protocol Service string + Node string Shard string key string @@ -208,7 +209,13 @@ func (w *SDWatcher) buildResult(kvs map[string][]byte) []ServiceAddress { if len(components) == 3 { sa.Protocol, _ = Layer4ProtocolFromString(components[0]) sa.Service = components[1][1:] + sa.Node = components[2] sa.Shard = components[2] + } else if len(components) == 4 { + sa.Protocol, _ = Layer4ProtocolFromString(components[0]) + sa.Service = components[1][1:] + sa.Node = components[2] + sa.Shard = components[3] } sas = append(sas, sa) } -- 2.50.1