Files
weave-scope/probe/resolver.go
Peter Bourgon 8602132ab6 Move concurrency from resolve to HTTP GET
- Process DNS resolution serially
- Process up to 10 HTTP GET (for app ID) concurrently

More than 10 concurrent GET requests will block on the semaphore. This
will cause the staticResolver.resolve method to block, which is probably
fine: it will just delay the next resolve loop, currently at 1m
intervals.

To make this a little bit more robust, I've also added a fastClient for
app ID resolution, with a timeout (total, including connect, request,
and response) of 5s.
2015-09-24 16:56:37 +02:00

112 lines
2.1 KiB
Go

package main
import (
"log"
"net"
"strconv"
"strings"
"time"
"github.com/weaveworks/scope/xfer"
)
var (
tick = time.Tick
lookupIP = net.LookupIP
)
type staticResolver struct {
set func(string, []string)
targets []target
quit chan struct{}
}
type target struct{ host, port string }
func (t target) String() string { return net.JoinHostPort(t.host, t.port) }
// newStaticResolver periodically resolves the targets, and calls the set
// function with all the resolved IPs. It explictiy supports targets which
// resolve to multiple IPs.
func newStaticResolver(targets []string, set func(target string, endpoints []string)) staticResolver {
r := staticResolver{
targets: prepare(targets),
set: set,
quit: make(chan struct{}),
}
go r.loop()
return r
}
func (r staticResolver) loop() {
r.resolve()
t := tick(time.Minute)
for {
select {
case <-t:
r.resolve()
case <-r.quit:
return
}
}
}
func (r staticResolver) Stop() {
close(r.quit)
}
func prepare(strs []string) []target {
var targets []target
for _, s := range strs {
var host, port string
if strings.Contains(s, ":") {
var err error
host, port, err = net.SplitHostPort(s)
if err != nil {
log.Printf("invalid address %s: %v", s, err)
continue
}
} else {
host, port = s, strconv.Itoa(xfer.AppPort)
}
targets = append(targets, target{host, port})
}
return targets
}
func (r staticResolver) resolve() {
for t, endpoints := range resolveMany(r.targets) {
r.set(t.String(), endpoints)
}
}
func resolveMany(targets []target) map[target][]string {
result := map[target][]string{}
for _, t := range targets {
result[t] = resolveOne(t)
}
return result
}
func resolveOne(t target) []string {
var addrs []net.IP
if addr := net.ParseIP(t.host); addr != nil {
addrs = []net.IP{addr}
} else {
var err error
addrs, err = lookupIP(t.host)
if err != nil {
return []string{}
}
}
endpoints := make([]string, 0, len(addrs))
for _, addr := range addrs {
// For now, ignore IPv6
if addr.To4() == nil {
continue
}
endpoints = append(endpoints, net.JoinHostPort(addr.String(), t.port))
}
return endpoints
}