middleware/proxy: make it scale (#287)

* middleware/proxy

Use connection pooling for communicating with an upstream, instead of
opening a new socket every time.

This makes the proxy more efficient and allowed for some cleanups.

* Some cleanups

* Some fixes

* more

* Kill pool

* Add nil check

* remove pool
This commit is contained in:
Miek Gieben 2016-10-08 14:46:22 +01:00 committed by GitHub
parent f29f622ec7
commit a05901f62a
9 changed files with 159 additions and 388 deletions

View file

@ -14,19 +14,13 @@ import (
var errUnreachable = errors.New("unreachable backend")
// Proxy represents a middleware instance that can proxy requests.
// Proxy represents a middleware instance that can proxy requests to another DNS server.
type Proxy struct {
Next middleware.Handler
Client Client
Client *Client
Upstreams []Upstream
}
// Client represents client information that the proxy uses.
type Client struct {
UDP *dns.Client
TCP *dns.Client
}
// Upstream manages a pool of proxy upstream hosts. Select should return a
// suitable upstream host, or nil if no such hosts are available.
type Upstream interface {
@ -82,12 +76,15 @@ func (p Proxy) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
if host == nil {
return dns.RcodeServerFailure, errUnreachable
}
reverseproxy := ReverseProxy{Host: host.Name, Client: p.Client, Options: upstream.Options()}
atomic.AddInt64(&host.Conns, 1)
backendErr := reverseproxy.ServeDNS(w, r, nil)
reply, backendErr := p.Client.ServeDNS(w, r, host)
atomic.AddInt64(&host.Conns, -1)
if backendErr == nil {
w.WriteMsg(reply)
return 0, nil
}
timeout := host.FailTimeout
@ -105,19 +102,5 @@ func (p Proxy) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
return p.Next.ServeDNS(ctx, w, r)
}
// Clients returns the new client for proxy requests.
func Clients() Client {
udp := newClient("udp", defaultTimeout)
tcp := newClient("tcp", defaultTimeout)
return Client{UDP: udp, TCP: tcp}
}
// newClient returns a new client for proxy requests.
func newClient(net string, timeout time.Duration) *dns.Client {
if timeout == 0 {
timeout = defaultTimeout
}
return &dns.Client{Net: net, ReadTimeout: timeout, WriteTimeout: timeout, SingleInflight: true}
}
// defaultTimeout is the default networking timeout for DNS requests.
const defaultTimeout = 5 * time.Second