Create a gist now

Instantly share code, notes, and snippets.

Cache DNS responses and refresh them using a single goroutine on a 1 minute timer. Avoids having a spike of threads from cgo launched under load.
package dnscache
import (
"net"
"sync"
"time"
"math/rand"
)
var (
lock = new(sync.RWMutex)
resolved = make(map[string]string, 32)
)
func init() {
go refresh()
}
func Lookup(address string) (string, error) {
lock.RLock()
ip, exists := resolved[address]
lock.RUnlock()
if exists { return ip, nil }
return lookup(address)
}
func refresh() {
for {
time.Sleep(time.Minute * 1)
var addresses []string
lock.RLock()
for key, _ := range resolved {
addresses = append(addresses, key)
}
lock.RUnlock()
for _, address := range addresses {
lookup(address)
time.Sleep(time.Second * 5)
}
}
}
func lookup(address string) (string, error) {
ips, err := net.LookupIP(address)
if err != nil { return "", err }
ip := ips[rand.Int31n(int32(len(ips)))].String()
lock.Lock()
resolved[address] = ip
lock.Unlock()
return ip, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment