plugins/forward: Add max_concurrent option (#3640)
* count and limit concurrent queries Signed-off-by: Chris O'Haver <cohaver@infoblox.com> * add option Signed-off-by: Chris O'Haver <cohaver@infoblox.com> * return servfail when limit exceeded Signed-off-by: Chris O'Haver <cohaver@infoblox.com> * docs Signed-off-by: Chris O'Haver <cohaver@infoblox.com> * docs Signed-off-by: Chris O'Haver <cohaver@infoblox.com> * docs Signed-off-by: Chris O'Haver <cohaver@infoblox.com> * review feedback Signed-off-by: Chris O'Haver <cohaver@infoblox.com> * move atomic counter to beginning of struct Signed-off-by: Chris O'Haver <cohaver@infoblox.com> * add comment for ErrLimitExceeded Signed-off-by: Chris O'Haver <cohaver@infoblox.com> * rename option to max_concurrent Signed-off-by: Chris O'Haver <cohaver@infoblox.com> * add metric Signed-off-by: Chris O'Haver <cohaver@infoblox.com> * response REFUSED; incl max in error; add more docs Signed-off-by: Chris O'Haver <cohaver@infoblox.com> * avoid err setup race Signed-off-by: Chris O'Haver <cohaver@infoblox.com> * respond SERVFAIL; doc memory usage Signed-off-by: Chris O'Haver <cohaver@infoblox.com>
This commit is contained in:
parent
8724a134c4
commit
22cd28a798
5 changed files with 85 additions and 2 deletions
|
@ -8,6 +8,7 @@ import (
|
|||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/coredns/coredns/plugin"
|
||||
|
@ -25,6 +26,8 @@ var log = clog.NewWithPlugin("forward")
|
|||
// Forward represents a plugin instance that can proxy requests to another (DNS) server. It has a list
|
||||
// of proxies each representing one upstream proxy.
|
||||
type Forward struct {
|
||||
concurrent int64 // atomic counters need to be first in struct for proper alignment
|
||||
|
||||
proxies []*Proxy
|
||||
p policy.Policy
|
||||
hcInterval time.Duration
|
||||
|
@ -36,9 +39,14 @@ type Forward struct {
|
|||
tlsServerName string
|
||||
maxfails uint32
|
||||
expire time.Duration
|
||||
maxConcurrent int64
|
||||
|
||||
opts options // also here for testing
|
||||
|
||||
// ErrLimitExceeded indicates that a query was rejected because the number of concurrent queries has exceeded
|
||||
// the maximum allowed (maxConcurrent)
|
||||
ErrLimitExceeded error
|
||||
|
||||
Next plugin.Handler
|
||||
}
|
||||
|
||||
|
@ -68,6 +76,15 @@ func (f *Forward) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg
|
|||
return plugin.NextOrFailure(f.Name(), f.Next, ctx, w, r)
|
||||
}
|
||||
|
||||
if f.maxConcurrent > 0 {
|
||||
count := atomic.AddInt64(&(f.concurrent), 1)
|
||||
defer atomic.AddInt64(&(f.concurrent), -1)
|
||||
if count > f.maxConcurrent {
|
||||
MaxConcurrentRejectCount.Add(1)
|
||||
return dns.RcodeServerFailure, f.ErrLimitExceeded
|
||||
}
|
||||
}
|
||||
|
||||
fails := 0
|
||||
var span, child ot.Span
|
||||
var upstreamErr error
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue