|
|
@ -17,7 +17,7 @@ import (
|
|
|
|
const (
|
|
|
|
const (
|
|
|
|
defaultBuckets = 50
|
|
|
|
defaultBuckets = 50
|
|
|
|
defaultWindow = time.Second * 5
|
|
|
|
defaultWindow = time.Second * 5
|
|
|
|
// using 1000m notation, 900m is like 80%, keep it as var for unit test
|
|
|
|
// using 1000m notation, 900m is like 90%, keep it as var for unit test
|
|
|
|
defaultCpuThreshold = 900
|
|
|
|
defaultCpuThreshold = 900
|
|
|
|
defaultMinRt = float64(time.Second / time.Millisecond)
|
|
|
|
defaultMinRt = float64(time.Second / time.Millisecond)
|
|
|
|
// moving average hyperparameter beta for calculating requests on the fly
|
|
|
|
// moving average hyperparameter beta for calculating requests on the fly
|
|
|
@ -70,7 +70,7 @@ type (
|
|
|
|
flying int64
|
|
|
|
flying int64
|
|
|
|
avgFlying float64
|
|
|
|
avgFlying float64
|
|
|
|
avgFlyingLock syncx.SpinLock
|
|
|
|
avgFlyingLock syncx.SpinLock
|
|
|
|
dropTime *syncx.AtomicDuration
|
|
|
|
overloadTime *syncx.AtomicDuration
|
|
|
|
droppedRecently *syncx.AtomicBool
|
|
|
|
droppedRecently *syncx.AtomicBool
|
|
|
|
passCounter *collection.RollingWindow
|
|
|
|
passCounter *collection.RollingWindow
|
|
|
|
rtCounter *collection.RollingWindow
|
|
|
|
rtCounter *collection.RollingWindow
|
|
|
@ -106,7 +106,7 @@ func NewAdaptiveShedder(opts ...ShedderOption) Shedder {
|
|
|
|
return &adaptiveShedder{
|
|
|
|
return &adaptiveShedder{
|
|
|
|
cpuThreshold: options.cpuThreshold,
|
|
|
|
cpuThreshold: options.cpuThreshold,
|
|
|
|
windows: int64(time.Second / bucketDuration),
|
|
|
|
windows: int64(time.Second / bucketDuration),
|
|
|
|
dropTime: syncx.NewAtomicDuration(),
|
|
|
|
overloadTime: syncx.NewAtomicDuration(),
|
|
|
|
droppedRecently: syncx.NewAtomicBool(),
|
|
|
|
droppedRecently: syncx.NewAtomicBool(),
|
|
|
|
passCounter: collection.NewRollingWindow(options.buckets, bucketDuration,
|
|
|
|
passCounter: collection.NewRollingWindow(options.buckets, bucketDuration,
|
|
|
|
collection.IgnoreCurrentBucket()),
|
|
|
|
collection.IgnoreCurrentBucket()),
|
|
|
@ -118,7 +118,6 @@ func NewAdaptiveShedder(opts ...ShedderOption) Shedder {
|
|
|
|
// Allow implements Shedder.Allow.
|
|
|
|
// Allow implements Shedder.Allow.
|
|
|
|
func (as *adaptiveShedder) Allow() (Promise, error) {
|
|
|
|
func (as *adaptiveShedder) Allow() (Promise, error) {
|
|
|
|
if as.shouldDrop() {
|
|
|
|
if as.shouldDrop() {
|
|
|
|
as.dropTime.Set(timex.Now())
|
|
|
|
|
|
|
|
as.droppedRecently.Set(true)
|
|
|
|
as.droppedRecently.Set(true)
|
|
|
|
|
|
|
|
|
|
|
|
return nil, ErrServiceOverloaded
|
|
|
|
return nil, ErrServiceOverloaded
|
|
|
@ -215,21 +214,26 @@ func (as *adaptiveShedder) stillHot() bool {
|
|
|
|
return false
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
dropTime := as.dropTime.Load()
|
|
|
|
overloadTime := as.overloadTime.Load()
|
|
|
|
if dropTime == 0 {
|
|
|
|
if overloadTime == 0 {
|
|
|
|
return false
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
hot := timex.Since(dropTime) < coolOffDuration
|
|
|
|
if timex.Since(overloadTime) < coolOffDuration {
|
|
|
|
if !hot {
|
|
|
|
return true
|
|
|
|
as.droppedRecently.Set(false)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return hot
|
|
|
|
as.droppedRecently.Set(false)
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (as *adaptiveShedder) systemOverloaded() bool {
|
|
|
|
func (as *adaptiveShedder) systemOverloaded() bool {
|
|
|
|
return systemOverloadChecker(as.cpuThreshold)
|
|
|
|
if !systemOverloadChecker(as.cpuThreshold) {
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
as.overloadTime.Set(timex.Now())
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// WithBuckets customizes the Shedder with given number of buckets.
|
|
|
|
// WithBuckets customizes the Shedder with given number of buckets.
|
|
|
|