Hi Nuts,

net.LookupHost is taking a long time (up to 5 seconds) to resolve
localhost, where I expect it to be instant. At other times it can take
anywhere from 1-100ms, but it seems to reliably return a result shortly
after 5 seconds.

The details:

* I'm doing local development inside a docker container (alpine linux:
`docker run alpine sh`). Outside of this environment I can't seem to easily
get the problem to manifest, but I haven't tried hard.

* The problem manifests as many things having an additional random amount
of latency of order 100ms-5s.

* Inside the container, various services are talking to each other through
URLs which read `http://localhost:...`

* Resolv.conf has `nameserver 8.8.8.8` which may or may not be unreachable
at different times. If it is unreachable, then it takes 5 seconds to
resolve localhost.

* I'm on a slow mobile network, so I hit this frequently.

* I experience 5 second timeouts even on fast networks where the resolver
should be reachable, though this could perhaps be explained by an
out-of-date resolv.conf inside the docker container.

* Tweaking GODEBUG=netdns= to either go or cgo seems to fix the problem.

* The presence or absense of an empty /etc/nsswitch.conf has no effect.

* An empty resolv.conf still selects "dns,files" but then returns a result
fast (in microseconds).

My test program:

func main() {
    start := time.Now()
    _, err := net.LookupHost("localhost")
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("Took %v", time.Since(start))
}

This seems to be the fundamental problem:

# GODEBUG=netdns=2 ./tmp-1
go package net: dynamic selection of DNS resolver
go package net: hostLookupOrder(localhost) = dns,files
Took 351.143424ms

Why is go choosing "dns,files"? If I choose either cgo or go as my resolver
(see end of mail), it correctly chooses `files,dns` then everything goes
quickly, taking microseconds rather than hundreds of milliseconds.

On a Debian host, it seems to correctly select `files,dns`.

Am I missing something?

Also, in the interests of trimming latency, is there any reason the Go
resolver shouldn't just directly return 127.0.0.1 as a hard-coded result
for "localhost"? I understood it may be required by the RFC, but the
strongest language I could find was in RFC2606:


      The ".localhost" TLD has traditionally been statically defined in
      host DNS implementations as having an A record pointing to the
      loop back IP address and is reserved for such use.  Any other use
      would conflict with widely deployed code which assumes this use.


Thanks,

- Peter

Selecting either resolver has the correct behaviour, compared with that
shown above:

# GODEBUG=netdns=go+2 ./tmp-1
go package net: GODEBUG setting forcing use of Go's resolver
go package net: hostLookupOrder(localhost) = files,dns
Took 376.164µs

# GODEBUG=netdns=cgo+2 ./tmp-1
go package net: using cgo DNS resolver
go package net: hostLookupOrder(localhost) = cgo
Took 102.334µs

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to