config: add jitter interval for watcher to avoid dos

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
2021-08-04 00:37:56 +03:00
parent 1e8e57a708
commit f47fbb1030
6 changed files with 86 additions and 14 deletions

View File

@@ -10,8 +10,11 @@ import (
// DefaultConfig default config
var DefaultConfig Config = NewConfig()
// DefaultWatcherInterval default interval for poll changes
var DefaultWatcherInterval = 5 * time.Second
// DefaultWatcherMinInterval default min interval for poll changes
var DefaultWatcherMinInterval = 5 * time.Second
// DefaultWatcherMinInterval default max interval for poll changes
var DefaultWatcherMaxInterval = 9 * time.Second
var (
// ErrCodecMissing is returned when codec needed and not specified

View File

@@ -5,9 +5,9 @@ import (
"reflect"
"strconv"
"strings"
"time"
"github.com/imdario/mergo"
"github.com/unistack-org/micro/v3/util/jitter"
rutil "github.com/unistack-org/micro/v3/util/reflect"
)
@@ -302,7 +302,7 @@ type defaultWatcher struct {
}
func (w *defaultWatcher) run() {
ticker := time.NewTicker(w.wopts.Interval)
ticker := jitter.NewTicker(w.wopts.MinInterval, w.wopts.MaxInterval)
defer ticker.Stop()
src := w.opts.Struct

View File

@@ -31,7 +31,7 @@ func TestWatch(t *testing.T) {
t.Fatal(err)
}
w, err := cfg.Watch(ctx, config.WatchInterval(500*time.Millisecond))
w, err := cfg.Watch(ctx, config.WatchInterval(200*time.Millisecond, 500*time.Millisecond))
if err != nil {
t.Fatal(err)
}

View File

@@ -211,8 +211,10 @@ type WatchOptions struct {
Context context.Context
// Coalesce multiple events to one
Coalesce bool
// Interval to periodically pull changes if config source not supports async notify
Interval time.Duration
// MinInterval specifies the min time.Duration interval for poll changes
MinInterval time.Duration
// MaxInterval specifies the max time.Duration interval for poll changes
MaxInterval time.Duration
// Struct for filling
Struct interface{}
}
@@ -221,8 +223,9 @@ type WatchOption func(*WatchOptions)
func NewWatchOptions(opts ...WatchOption) WatchOptions {
options := WatchOptions{
Context: context.Background(),
Interval: DefaultWatcherInterval,
Context: context.Background(),
MinInterval: DefaultWatcherMinInterval,
MaxInterval: DefaultWatcherMaxInterval,
}
for _, o := range opts {
o(&options)
@@ -244,10 +247,11 @@ func WatchCoalesce(b bool) WatchOption {
}
}
// WatchInterval specifies time.Duration for pulling changes
func WatchInterval(td time.Duration) WatchOption {
// WatchInterval specifies min and max time.Duration for pulling changes
func WatchInterval(min, max time.Duration) WatchOption {
return func(o *WatchOptions) {
o.Interval = td
o.MinInterval = min
o.MaxInterval = max
}
}