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:
parent
f29f622ec7
commit
a05901f62a
9 changed files with 159 additions and 388 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue