-
Notifications
You must be signed in to change notification settings - Fork 1
/
consul_dns.go
71 lines (62 loc) · 1.69 KB
/
consul_dns.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package main
import (
"context"
"fmt"
"math/rand"
"net"
"strings"
"time"
)
func NewConsulDNS() *ConsulDNS {
consulDnsAddr := strings.Replace(ConsulAddr, "8500", "8600", 1)
consulDnsAddr = strings.Replace(consulDnsAddr, "http://", "", 1)
consulDnsAddr = strings.Replace(consulDnsAddr, "https://", "", 1)
return &ConsulDNS{
r: &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
d := net.Dialer{}
return d.DialContext(ctx, "udp", consulDnsAddr)
},
},
ctx: context.Background(),
}
}
type ConsulDNS struct {
r *net.Resolver
ctx context.Context
}
func (c *ConsulDNS) GetServiceAddr(serviceName string) (addr string, err error) {
for x := 0; x < 5; x++ {
jitter := time.Duration(rand.Intn(100))
time.Sleep(jitter * time.Millisecond)
addr, err = c.GetServiceAddrOnce(serviceName)
if err == nil {
return
}
sleep := time.Duration(x * 100)
time.Sleep(sleep * time.Millisecond)
}
return
}
func (c *ConsulDNS) GetServiceAddrOnce(serviceName string) (addr string, err error) {
name := serviceName + ".service." + datacenter + ".consul"
_, addrs, err := c.r.LookupSRV(c.ctx, "", "", name)
if err != nil {
return "", fmt.Errorf("Error getting SRV record for %s: %w", name, err)
}
if len(addrs) < 1 {
return "", fmt.Errorf("%s: got no addrs :(", name)
}
// there should be only one addr in our case.
target := addrs[0].Target
port := addrs[0].Port
ips, err := c.r.LookupHost(c.ctx, target)
if err != nil {
return "", fmt.Errorf("Error looking up host for %s: %w", target, err)
}
if len(ips) < 1 {
return "", fmt.Errorf("%s: got no ips :(", target)
}
return fmt.Sprintf("%s:%d", ips[0], port), nil
}