mirror of
https://github.com/zeromicro/go-zero.git
synced 2025-01-23 09:00:20 +08:00
optimize: shedding algorithm performance (#3908)
This commit is contained in:
parent
8ceb2885db
commit
9c17499757
@ -12,7 +12,7 @@ type RestfulConf struct {
|
|||||||
MaxConns int `json:",default=10000"`
|
MaxConns int `json:",default=10000"`
|
||||||
MaxBytes int64 `json:",default=1048576"`
|
MaxBytes int64 `json:",default=1048576"`
|
||||||
Timeout time.Duration `json:",default=3s"`
|
Timeout time.Duration `json:",default=3s"`
|
||||||
CpuThreshold int64 `json:",default=900,range=[0:1000]"`
|
CpuThreshold int64 `json:",default=900,range=[0:1000)"`
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/zeromicro/go-zero/core/collection"
|
"github.com/zeromicro/go-zero/core/collection"
|
||||||
"github.com/zeromicro/go-zero/core/logx"
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"github.com/zeromicro/go-zero/core/mathx"
|
||||||
"github.com/zeromicro/go-zero/core/stat"
|
"github.com/zeromicro/go-zero/core/stat"
|
||||||
"github.com/zeromicro/go-zero/core/syncx"
|
"github.com/zeromicro/go-zero/core/syncx"
|
||||||
"github.com/zeromicro/go-zero/core/timex"
|
"github.com/zeromicro/go-zero/core/timex"
|
||||||
@ -21,8 +22,11 @@ const (
|
|||||||
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
|
||||||
flyingBeta = 0.9
|
flyingBeta = 0.9
|
||||||
coolOffDuration = time.Second
|
coolOffDuration = time.Second
|
||||||
|
cpuMax = 1000 // millicpu
|
||||||
|
millisecondsPerSecond = 1000
|
||||||
|
overloadFactorLowerBound = 0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -66,7 +70,7 @@ type (
|
|||||||
|
|
||||||
adaptiveShedder struct {
|
adaptiveShedder struct {
|
||||||
cpuThreshold int64
|
cpuThreshold int64
|
||||||
windows int64
|
windowScale float64
|
||||||
flying int64
|
flying int64
|
||||||
avgFlying float64
|
avgFlying float64
|
||||||
avgFlyingLock syncx.SpinLock
|
avgFlyingLock syncx.SpinLock
|
||||||
@ -105,7 +109,7 @@ func NewAdaptiveShedder(opts ...ShedderOption) Shedder {
|
|||||||
bucketDuration := options.window / time.Duration(options.buckets)
|
bucketDuration := options.window / time.Duration(options.buckets)
|
||||||
return &adaptiveShedder{
|
return &adaptiveShedder{
|
||||||
cpuThreshold: options.cpuThreshold,
|
cpuThreshold: options.cpuThreshold,
|
||||||
windows: int64(time.Second / bucketDuration),
|
windowScale: float64(time.Second) / float64(bucketDuration) / millisecondsPerSecond,
|
||||||
overloadTime: syncx.NewAtomicDuration(),
|
overloadTime: syncx.NewAtomicDuration(),
|
||||||
droppedRecently: syncx.NewAtomicBool(),
|
droppedRecently: syncx.NewAtomicBool(),
|
||||||
passCounter: collection.NewRollingWindow(options.buckets, bucketDuration,
|
passCounter: collection.NewRollingWindow(options.buckets, bucketDuration,
|
||||||
@ -149,16 +153,17 @@ func (as *adaptiveShedder) highThru() bool {
|
|||||||
as.avgFlyingLock.Lock()
|
as.avgFlyingLock.Lock()
|
||||||
avgFlying := as.avgFlying
|
avgFlying := as.avgFlying
|
||||||
as.avgFlyingLock.Unlock()
|
as.avgFlyingLock.Unlock()
|
||||||
maxFlight := as.maxFlight()
|
maxFlight := as.maxFlight() * as.overloadFactor()
|
||||||
return int64(avgFlying) > maxFlight && atomic.LoadInt64(&as.flying) > maxFlight
|
return avgFlying > maxFlight && float64(atomic.LoadInt64(&as.flying)) > maxFlight
|
||||||
}
|
}
|
||||||
|
|
||||||
func (as *adaptiveShedder) maxFlight() int64 {
|
func (as *adaptiveShedder) maxFlight() float64 {
|
||||||
// windows = buckets per second
|
// windows = buckets per second
|
||||||
// maxQPS = maxPASS * windows
|
// maxQPS = maxPASS * windows
|
||||||
// minRT = min average response time in milliseconds
|
// minRT = min average response time in milliseconds
|
||||||
// maxQPS * minRT / milliseconds_per_second
|
// allowedFlying = maxQPS * minRT / milliseconds_per_second
|
||||||
return int64(math.Max(1, float64(as.maxPass()*as.windows)*(as.minRt()/1e3)))
|
maxFlight := float64(as.maxPass()) * as.minRt() * as.windowScale
|
||||||
|
return mathx.AtLeast(maxFlight, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (as *adaptiveShedder) maxPass() int64 {
|
func (as *adaptiveShedder) maxPass() int64 {
|
||||||
@ -174,6 +179,8 @@ func (as *adaptiveShedder) maxPass() int64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (as *adaptiveShedder) minRt() float64 {
|
func (as *adaptiveShedder) minRt() float64 {
|
||||||
|
// if no requests in previous windows, return defaultMinRt,
|
||||||
|
// its a reasonable large value to avoid dropping requests.
|
||||||
result := defaultMinRt
|
result := defaultMinRt
|
||||||
|
|
||||||
as.rtCounter.Reduce(func(b *collection.Bucket) {
|
as.rtCounter.Reduce(func(b *collection.Bucket) {
|
||||||
@ -190,6 +197,13 @@ func (as *adaptiveShedder) minRt() float64 {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (as *adaptiveShedder) overloadFactor() float64 {
|
||||||
|
// as.cpuThreshold must be less than cpuMax
|
||||||
|
factor := (cpuMax - float64(stat.CpuUsage())) / (cpuMax - float64(as.cpuThreshold))
|
||||||
|
// at least accept 10% of acceptable requests even cpu is highly overloaded.
|
||||||
|
return mathx.Between(factor, overloadFactorLowerBound, 1)
|
||||||
|
}
|
||||||
|
|
||||||
func (as *adaptiveShedder) shouldDrop() bool {
|
func (as *adaptiveShedder) shouldDrop() bool {
|
||||||
if as.systemOverloaded() || as.stillHot() {
|
if as.systemOverloaded() || as.stillHot() {
|
||||||
if as.highThru() {
|
if as.highThru() {
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
buckets = 10
|
buckets = 10
|
||||||
bucketDuration = time.Millisecond * 50
|
bucketDuration = time.Millisecond * 50
|
||||||
|
windowFactor = 0.01
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -114,10 +115,10 @@ func TestAdaptiveShedderMaxFlight(t *testing.T) {
|
|||||||
shedder := &adaptiveShedder{
|
shedder := &adaptiveShedder{
|
||||||
passCounter: passCounter,
|
passCounter: passCounter,
|
||||||
rtCounter: rtCounter,
|
rtCounter: rtCounter,
|
||||||
windows: buckets,
|
windowScale: windowFactor,
|
||||||
droppedRecently: syncx.NewAtomicBool(),
|
droppedRecently: syncx.NewAtomicBool(),
|
||||||
}
|
}
|
||||||
assert.Equal(t, int64(54), shedder.maxFlight())
|
assert.Equal(t, float64(54), shedder.maxFlight())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAdaptiveShedderShouldDrop(t *testing.T) {
|
func TestAdaptiveShedderShouldDrop(t *testing.T) {
|
||||||
@ -136,7 +137,7 @@ func TestAdaptiveShedderShouldDrop(t *testing.T) {
|
|||||||
shedder := &adaptiveShedder{
|
shedder := &adaptiveShedder{
|
||||||
passCounter: passCounter,
|
passCounter: passCounter,
|
||||||
rtCounter: rtCounter,
|
rtCounter: rtCounter,
|
||||||
windows: buckets,
|
windowScale: windowFactor,
|
||||||
overloadTime: syncx.NewAtomicDuration(),
|
overloadTime: syncx.NewAtomicDuration(),
|
||||||
droppedRecently: syncx.NewAtomicBool(),
|
droppedRecently: syncx.NewAtomicBool(),
|
||||||
}
|
}
|
||||||
@ -149,7 +150,8 @@ func TestAdaptiveShedderShouldDrop(t *testing.T) {
|
|||||||
|
|
||||||
// cpu >= 800, inflight > maxPass
|
// cpu >= 800, inflight > maxPass
|
||||||
shedder.avgFlying = 80
|
shedder.avgFlying = 80
|
||||||
shedder.flying = 50
|
// because of the overloadFactor, so we need to make sure maxFlight is greater than flying
|
||||||
|
shedder.flying = int64(shedder.maxFlight()*shedder.overloadFactor()) - 5
|
||||||
assert.False(t, shedder.shouldDrop())
|
assert.False(t, shedder.shouldDrop())
|
||||||
|
|
||||||
// cpu >= 800, inflight > maxPass
|
// cpu >= 800, inflight > maxPass
|
||||||
@ -190,7 +192,7 @@ func TestAdaptiveShedderStillHot(t *testing.T) {
|
|||||||
shedder := &adaptiveShedder{
|
shedder := &adaptiveShedder{
|
||||||
passCounter: passCounter,
|
passCounter: passCounter,
|
||||||
rtCounter: rtCounter,
|
rtCounter: rtCounter,
|
||||||
windows: buckets,
|
windowScale: windowFactor,
|
||||||
overloadTime: syncx.NewAtomicDuration(),
|
overloadTime: syncx.NewAtomicDuration(),
|
||||||
droppedRecently: syncx.ForAtomicBool(true),
|
droppedRecently: syncx.ForAtomicBool(true),
|
||||||
}
|
}
|
||||||
@ -239,6 +241,30 @@ func BenchmarkAdaptiveShedder_Allow(b *testing.B) {
|
|||||||
b.Run("low load", bench)
|
b.Run("low load", bench)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkMaxFlight(b *testing.B) {
|
||||||
|
passCounter := newRollingWindow()
|
||||||
|
rtCounter := newRollingWindow()
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
if i > 0 {
|
||||||
|
time.Sleep(bucketDuration)
|
||||||
|
}
|
||||||
|
passCounter.Add(float64((i + 1) * 100))
|
||||||
|
for j := i*10 + 1; j <= i*10+10; j++ {
|
||||||
|
rtCounter.Add(float64(j))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shedder := &adaptiveShedder{
|
||||||
|
passCounter: passCounter,
|
||||||
|
rtCounter: rtCounter,
|
||||||
|
windowScale: windowFactor,
|
||||||
|
droppedRecently: syncx.NewAtomicBool(),
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_ = shedder.maxFlight()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func newRollingWindow() *collection.RollingWindow {
|
func newRollingWindow() *collection.RollingWindow {
|
||||||
return collection.NewRollingWindow(buckets, bucketDuration, collection.IgnoreCurrentBucket())
|
return collection.NewRollingWindow(buckets, bucketDuration, collection.IgnoreCurrentBucket())
|
||||||
}
|
}
|
||||||
|
34
core/mathx/range.go
Normal file
34
core/mathx/range.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package mathx
|
||||||
|
|
||||||
|
type numerical interface {
|
||||||
|
~int | ~int8 | ~int16 | ~int32 | ~int64 |
|
||||||
|
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 |
|
||||||
|
~float32 | ~float64
|
||||||
|
}
|
||||||
|
|
||||||
|
// AtLeast returns the greater of x or lower.
|
||||||
|
func AtLeast[T numerical](x, lower T) T {
|
||||||
|
if x < lower {
|
||||||
|
return lower
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
// AtMost returns the smaller of x or upper.
|
||||||
|
func AtMost[T numerical](x, upper T) T {
|
||||||
|
if x > upper {
|
||||||
|
return upper
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
// Between returns the value of x clamped to the range [lower, upper].
|
||||||
|
func Between[T numerical](x, lower, upper T) T {
|
||||||
|
if x < lower {
|
||||||
|
return lower
|
||||||
|
}
|
||||||
|
if x > upper {
|
||||||
|
return upper
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
513
core/mathx/range_test.go
Normal file
513
core/mathx/range_test.go
Normal file
@ -0,0 +1,513 @@
|
|||||||
|
package mathx
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestAtLeast(t *testing.T) {
|
||||||
|
t.Run("test int", func(t *testing.T) {
|
||||||
|
if got := AtLeast(10, 5); got != 10 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 10", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(3, 5); got != 5 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(5, 5); got != 5 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test int8", func(t *testing.T) {
|
||||||
|
if got := AtLeast(int8(10), int8(5)); got != 10 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 10", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(int8(3), int8(5)); got != 5 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(int8(5), int8(5)); got != 5 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test int16", func(t *testing.T) {
|
||||||
|
if got := AtLeast(int16(10), int16(5)); got != 10 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 10", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(int16(3), int16(5)); got != 5 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(int16(5), int16(5)); got != 5 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test int32", func(t *testing.T) {
|
||||||
|
if got := AtLeast(int32(10), int32(5)); got != 10 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 10", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(int32(3), int32(5)); got != 5 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(int32(5), int32(5)); got != 5 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test int64", func(t *testing.T) {
|
||||||
|
if got := AtLeast(int64(10), int64(5)); got != 10 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 10", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(int64(3), int64(5)); got != 5 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(int64(5), int64(5)); got != 5 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test uint", func(t *testing.T) {
|
||||||
|
if got := AtLeast(uint(10), uint(5)); got != 10 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 10", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(uint(3), uint(5)); got != 5 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(uint(5), uint(5)); got != 5 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test uint8", func(t *testing.T) {
|
||||||
|
if got := AtLeast(uint8(10), uint8(5)); got != 10 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 10", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(uint8(3), uint8(5)); got != 5 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(uint8(5), uint8(5)); got != 5 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test uint16", func(t *testing.T) {
|
||||||
|
if got := AtLeast(uint16(10), uint16(5)); got != 10 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 10", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(uint16(3), uint16(5)); got != 5 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(uint16(5), uint16(5)); got != 5 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test uint32", func(t *testing.T) {
|
||||||
|
if got := AtLeast(uint32(10), uint32(5)); got != 10 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 10", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(uint32(3), uint32(5)); got != 5 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(uint32(5), uint32(5)); got != 5 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test uint64", func(t *testing.T) {
|
||||||
|
if got := AtLeast(uint64(10), uint64(5)); got != 10 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 10", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(uint64(3), uint64(5)); got != 5 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(uint64(5), uint64(5)); got != 5 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test float32", func(t *testing.T) {
|
||||||
|
if got := AtLeast(float32(10.0), float32(5.0)); got != 10.0 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 10.0", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(float32(3.0), float32(5.0)); got != 5.0 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5.0", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(float32(5.0), float32(5.0)); got != 5.0 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5.0", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test float64", func(t *testing.T) {
|
||||||
|
if got := AtLeast(10.0, 5.0); got != 10.0 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 10.0", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(3.0, 5.0); got != 5.0 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5.0", got)
|
||||||
|
}
|
||||||
|
if got := AtLeast(5.0, 5.0); got != 5.0 {
|
||||||
|
t.Errorf("AtLeast() = %v, want 5.0", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAtMost(t *testing.T) {
|
||||||
|
t.Run("test int", func(t *testing.T) {
|
||||||
|
if got := AtMost(10, 5); got != 5 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(3, 5); got != 3 {
|
||||||
|
t.Errorf("AtMost() = %v, want 3", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(5, 5); got != 5 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test int8", func(t *testing.T) {
|
||||||
|
if got := AtMost(int8(10), int8(5)); got != 5 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(int8(3), int8(5)); got != 3 {
|
||||||
|
t.Errorf("AtMost() = %v, want 3", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(int8(5), int8(5)); got != 5 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test int16", func(t *testing.T) {
|
||||||
|
if got := AtMost(int16(10), int16(5)); got != 5 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(int16(3), int16(5)); got != 3 {
|
||||||
|
t.Errorf("AtMost() = %v, want 3", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(int16(5), int16(5)); got != 5 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test int32", func(t *testing.T) {
|
||||||
|
if got := AtMost(int32(10), int32(5)); got != 5 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(int32(3), int32(5)); got != 3 {
|
||||||
|
t.Errorf("AtMost() = %v, want 3", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(int32(5), int32(5)); got != 5 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test int64", func(t *testing.T) {
|
||||||
|
if got := AtMost(int64(10), int64(5)); got != 5 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(int64(3), int64(5)); got != 3 {
|
||||||
|
t.Errorf("AtMost() = %v, want 3", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(int64(5), int64(5)); got != 5 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test uint", func(t *testing.T) {
|
||||||
|
if got := AtMost(uint(10), uint(5)); got != 5 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(uint(3), uint(5)); got != 3 {
|
||||||
|
t.Errorf("AtMost() = %v, want 3", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(uint(5), uint(5)); got != 5 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test uint8", func(t *testing.T) {
|
||||||
|
if got := AtMost(uint8(10), uint8(5)); got != 5 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(uint8(3), uint8(5)); got != 3 {
|
||||||
|
t.Errorf("AtMost() = %v, want 3", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(uint8(5), uint8(5)); got != 5 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test uint16", func(t *testing.T) {
|
||||||
|
if got := AtMost(uint16(10), uint16(5)); got != 5 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(uint16(3), uint16(5)); got != 3 {
|
||||||
|
t.Errorf("AtMost() = %v, want 3", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(uint16(5), uint16(5)); got != 5 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test uint32", func(t *testing.T) {
|
||||||
|
if got := AtMost(uint32(10), uint32(5)); got != 5 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(uint32(3), uint32(5)); got != 3 {
|
||||||
|
t.Errorf("AtMost() = %v, want 3", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(uint32(5), uint32(5)); got != 5 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test uint64", func(t *testing.T) {
|
||||||
|
if got := AtMost(uint64(10), uint64(5)); got != 5 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(uint64(3), uint64(5)); got != 3 {
|
||||||
|
t.Errorf("AtMost() = %v, want 3", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(uint64(5), uint64(5)); got != 5 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test float32", func(t *testing.T) {
|
||||||
|
if got := AtMost(float32(10.0), float32(5.0)); got != 5.0 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5.0", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(float32(3.0), float32(5.0)); got != 3.0 {
|
||||||
|
t.Errorf("AtMost() = %v, want 3.0", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(float32(5.0), float32(5.0)); got != 5.0 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5.0", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test float64", func(t *testing.T) {
|
||||||
|
if got := AtMost(10.0, 5.0); got != 5.0 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5.0", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(3.0, 5.0); got != 3.0 {
|
||||||
|
t.Errorf("AtMost() = %v, want 3.0", got)
|
||||||
|
}
|
||||||
|
if got := AtMost(5.0, 5.0); got != 5.0 {
|
||||||
|
t.Errorf("AtMost() = %v, want 5.0", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBetween(t *testing.T) {
|
||||||
|
t.Run("test int", func(t *testing.T) {
|
||||||
|
if got := Between(10, 5, 15); got != 10 {
|
||||||
|
t.Errorf("Between() = %v, want 10", got)
|
||||||
|
}
|
||||||
|
if got := Between(3, 5, 15); got != 5 {
|
||||||
|
t.Errorf("Between() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := Between(20, 5, 15); got != 15 {
|
||||||
|
t.Errorf("Between() = %v, want 15", got)
|
||||||
|
}
|
||||||
|
if got := Between(5, 5, 15); got != 5 {
|
||||||
|
t.Errorf("Between() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := Between(15, 5, 15); got != 15 {
|
||||||
|
t.Errorf("Between() = %v, want 15", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test int8", func(t *testing.T) {
|
||||||
|
if got := Between(int8(10), int8(5), int8(15)); got != 10 {
|
||||||
|
t.Errorf("Between() = %v, want 10", got)
|
||||||
|
}
|
||||||
|
if got := Between(int8(3), int8(5), int8(15)); got != 5 {
|
||||||
|
t.Errorf("Between() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := Between(int8(20), int8(5), int8(15)); got != 15 {
|
||||||
|
t.Errorf("Between() = %v, want 15", got)
|
||||||
|
}
|
||||||
|
if got := Between(int8(5), int8(5), int8(15)); got != 5 {
|
||||||
|
t.Errorf("Between() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := Between(int8(15), int8(5), int8(15)); got != 15 {
|
||||||
|
t.Errorf("Between() = %v, want 15", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test int16", func(t *testing.T) {
|
||||||
|
if got := Between(int16(10), int16(5), int16(15)); got != 10 {
|
||||||
|
t.Errorf("Between() = %v, want 10", got)
|
||||||
|
}
|
||||||
|
if got := Between(int16(3), int16(5), int16(15)); got != 5 {
|
||||||
|
t.Errorf("Between() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := Between(int16(20), int16(5), int16(15)); got != 15 {
|
||||||
|
t.Errorf("Between() = %v, want 15", got)
|
||||||
|
}
|
||||||
|
if got := Between(int16(5), int16(5), int16(15)); got != 5 {
|
||||||
|
t.Errorf("Between() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := Between(int16(15), int16(5), int16(15)); got != 15 {
|
||||||
|
t.Errorf("Between() = %v, want 15", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test int32", func(t *testing.T) {
|
||||||
|
if got := Between(int32(10), int32(5), int32(15)); got != 10 {
|
||||||
|
t.Errorf("Between() = %v, want 10", got)
|
||||||
|
}
|
||||||
|
if got := Between(int32(3), int32(5), int32(15)); got != 5 {
|
||||||
|
t.Errorf("Between() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := Between(int32(20), int32(5), int32(15)); got != 15 {
|
||||||
|
t.Errorf("Between() = %v, want 15", got)
|
||||||
|
}
|
||||||
|
if got := Between(int32(5), int32(5), int32(15)); got != 5 {
|
||||||
|
t.Errorf("Between() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := Between(int32(15), int32(5), int32(15)); got != 15 {
|
||||||
|
t.Errorf("Between() = %v, want 15", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test int64", func(t *testing.T) {
|
||||||
|
if got := Between(int64(10), int64(5), int64(15)); got != 10 {
|
||||||
|
t.Errorf("Between() = %v, want 10", got)
|
||||||
|
}
|
||||||
|
if got := Between(int64(3), int64(5), int64(15)); got != 5 {
|
||||||
|
t.Errorf("Between() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := Between(int64(20), int64(5), int64(15)); got != 15 {
|
||||||
|
t.Errorf("Between() = %v, want 15", got)
|
||||||
|
}
|
||||||
|
if got := Between(int64(5), int64(5), int64(15)); got != 5 {
|
||||||
|
t.Errorf("Between() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := Between(int64(15), int64(5), int64(15)); got != 15 {
|
||||||
|
t.Errorf("Between() = %v, want 15", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test uint", func(t *testing.T) {
|
||||||
|
if got := Between(uint(10), uint(5), uint(15)); got != 10 {
|
||||||
|
t.Errorf("Between() = %v, want 10", got)
|
||||||
|
}
|
||||||
|
if got := Between(uint(3), uint(5), uint(15)); got != 5 {
|
||||||
|
t.Errorf("Between() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := Between(uint(20), uint(5), uint(15)); got != 15 {
|
||||||
|
t.Errorf("Between() = %v, want 15", got)
|
||||||
|
}
|
||||||
|
if got := Between(uint(5), uint(5), uint(15)); got != 5 {
|
||||||
|
t.Errorf("Between() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := Between(uint(15), uint(5), uint(15)); got != 15 {
|
||||||
|
t.Errorf("Between() = %v, want 15", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test uint8", func(t *testing.T) {
|
||||||
|
if got := Between(uint8(10), uint8(5), uint8(15)); got != 10 {
|
||||||
|
t.Errorf("Between() = %v, want 10", got)
|
||||||
|
}
|
||||||
|
if got := Between(uint8(3), uint8(5), uint8(15)); got != 5 {
|
||||||
|
t.Errorf("Between() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := Between(uint8(20), uint8(5), uint8(15)); got != 15 {
|
||||||
|
t.Errorf("Between() = %v, want 15", got)
|
||||||
|
}
|
||||||
|
if got := Between(uint8(5), uint8(5), uint8(15)); got != 5 {
|
||||||
|
t.Errorf("Between() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := Between(uint8(15), uint8(5), uint8(15)); got != 15 {
|
||||||
|
t.Errorf("Between() = %v, want 15", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test uint16", func(t *testing.T) {
|
||||||
|
if got := Between(uint16(10), uint16(5), uint16(15)); got != 10 {
|
||||||
|
t.Errorf("Between() = %v, want 10", got)
|
||||||
|
}
|
||||||
|
if got := Between(uint16(3), uint16(5), uint16(15)); got != 5 {
|
||||||
|
t.Errorf("Between() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := Between(uint16(20), uint16(5), uint16(15)); got != 15 {
|
||||||
|
t.Errorf("Between() = %v, want 15", got)
|
||||||
|
}
|
||||||
|
if got := Between(uint16(5), uint16(5), uint16(15)); got != 5 {
|
||||||
|
t.Errorf("Between() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := Between(uint16(15), uint16(5), uint16(15)); got != 15 {
|
||||||
|
t.Errorf("Between() = %v, want 15", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test uint32", func(t *testing.T) {
|
||||||
|
if got := Between(uint32(10), uint32(5), uint32(15)); got != 10 {
|
||||||
|
t.Errorf("Between() = %v, want 10", got)
|
||||||
|
}
|
||||||
|
if got := Between(uint32(3), uint32(5), uint32(15)); got != 5 {
|
||||||
|
t.Errorf("Between() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := Between(uint32(20), uint32(5), uint32(15)); got != 15 {
|
||||||
|
t.Errorf("Between() = %v, want 15", got)
|
||||||
|
}
|
||||||
|
if got := Between(uint32(5), uint32(5), uint32(15)); got != 5 {
|
||||||
|
t.Errorf("Between() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := Between(uint32(15), uint32(5), uint32(15)); got != 15 {
|
||||||
|
t.Errorf("Between() = %v, want 15", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test uint64", func(t *testing.T) {
|
||||||
|
if got := Between(uint64(10), uint64(5), uint64(15)); got != 10 {
|
||||||
|
t.Errorf("Between() = %v, want 10", got)
|
||||||
|
}
|
||||||
|
if got := Between(uint64(3), uint64(5), uint64(15)); got != 5 {
|
||||||
|
t.Errorf("Between() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := Between(uint64(20), uint64(5), uint64(15)); got != 15 {
|
||||||
|
t.Errorf("Between() = %v, want 15", got)
|
||||||
|
}
|
||||||
|
if got := Between(uint64(5), uint64(5), uint64(15)); got != 5 {
|
||||||
|
t.Errorf("Between() = %v, want 5", got)
|
||||||
|
}
|
||||||
|
if got := Between(uint64(15), uint64(5), uint64(15)); got != 15 {
|
||||||
|
t.Errorf("Between() = %v, want 15", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test float32", func(t *testing.T) {
|
||||||
|
if got := Between(float32(10.0), float32(5.0), float32(15.0)); got != 10.0 {
|
||||||
|
t.Errorf("Between() = %v, want 10.0", got)
|
||||||
|
}
|
||||||
|
if got := Between(float32(3.0), float32(5.0), float32(15.0)); got != 5.0 {
|
||||||
|
t.Errorf("Between() = %v, want 5.0", got)
|
||||||
|
}
|
||||||
|
if got := Between(float32(20.0), float32(5.0), float32(15.0)); got != 15.0 {
|
||||||
|
t.Errorf("Between() = %v, want 15.0", got)
|
||||||
|
}
|
||||||
|
if got := Between(float32(5.0), float32(5.0), float32(15.0)); got != 5.0 {
|
||||||
|
t.Errorf("Between() = %v, want 5.0", got)
|
||||||
|
}
|
||||||
|
if got := Between(float32(15.0), float32(5.0), float32(15.0)); got != 15.0 {
|
||||||
|
t.Errorf("Between() = %v, want 15.0", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("test float64", func(t *testing.T) {
|
||||||
|
if got := Between(10.0, 5.0, 15.0); got != 10.0 {
|
||||||
|
t.Errorf("Between() = %v, want 10.0", got)
|
||||||
|
}
|
||||||
|
if got := Between(3.0, 5.0, 15.0); got != 5.0 {
|
||||||
|
t.Errorf("Between() = %v, want 5.0", got)
|
||||||
|
}
|
||||||
|
if got := Between(20.0, 5.0, 15.0); got != 15.0 {
|
||||||
|
t.Errorf("Between() = %v, want 15.0", got)
|
||||||
|
}
|
||||||
|
if got := Between(5.0, 5.0, 15.0); got != 5.0 {
|
||||||
|
t.Errorf("Between() = %v, want 5.0", got)
|
||||||
|
}
|
||||||
|
if got := Between(15.0, 5.0, 15.0); got != 15.0 {
|
||||||
|
t.Errorf("Between() = %v, want 15.0", got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
@ -53,7 +53,7 @@ type (
|
|||||||
MaxBytes int64 `json:",default=1048576"`
|
MaxBytes int64 `json:",default=1048576"`
|
||||||
// milliseconds
|
// milliseconds
|
||||||
Timeout int64 `json:",default=3000"`
|
Timeout int64 `json:",default=3000"`
|
||||||
CpuThreshold int64 `json:",default=900,range=[0:1000]"`
|
CpuThreshold int64 `json:",default=900,range=[0:1000)"`
|
||||||
Signature SignatureConf `json:",optional"`
|
Signature SignatureConf `json:",optional"`
|
||||||
// There are default values for all the items in Middlewares.
|
// There are default values for all the items in Middlewares.
|
||||||
Middlewares MiddlewaresConf
|
Middlewares MiddlewaresConf
|
||||||
|
@ -18,7 +18,7 @@ var (
|
|||||||
Name: "duration_ms",
|
Name: "duration_ms",
|
||||||
Help: "http server requests duration(ms).",
|
Help: "http server requests duration(ms).",
|
||||||
Labels: []string{"path", "method"},
|
Labels: []string{"path", "method"},
|
||||||
Buckets: []float64{5, 10, 25, 50, 100, 250, 500, 1000},
|
Buckets: []float64{5, 10, 25, 50, 100, 250, 500, 750, 1000},
|
||||||
})
|
})
|
||||||
|
|
||||||
metricServerReqCodeTotal = metric.NewCounterVec(&metric.CounterVecOpts{
|
metricServerReqCodeTotal = metric.NewCounterVec(&metric.CounterVecOpts{
|
||||||
|
@ -43,7 +43,7 @@ type (
|
|||||||
StrictControl bool `json:",optional"`
|
StrictControl bool `json:",optional"`
|
||||||
// setting 0 means no timeout
|
// setting 0 means no timeout
|
||||||
Timeout int64 `json:",default=2000"`
|
Timeout int64 `json:",default=2000"`
|
||||||
CpuThreshold int64 `json:",default=900,range=[0:1000]"`
|
CpuThreshold int64 `json:",default=900,range=[0:1000)"`
|
||||||
// grpc health check switch
|
// grpc health check switch
|
||||||
Health bool `json:",default=true"`
|
Health bool `json:",default=true"`
|
||||||
Middlewares ServerMiddlewaresConf
|
Middlewares ServerMiddlewaresConf
|
||||||
|
Loading…
Reference in New Issue
Block a user