fix: the qps feature cannot work well (#201)
This commit is contained in:
parent
3f2877e6c2
commit
69e53b6e04
|
@ -15,6 +15,9 @@ jobs:
|
|||
- name: Unit Test
|
||||
run: |
|
||||
make test-all-backend test-operator
|
||||
- name: Long Test
|
||||
run: |
|
||||
make testlong
|
||||
- name: Report
|
||||
if: github.actor == 'linuxsuren'
|
||||
env:
|
||||
|
|
2
Makefile
2
Makefile
|
@ -46,6 +46,8 @@ plugin-git:
|
|||
test:
|
||||
go test ./... -cover -v -coverprofile=coverage.out
|
||||
go tool cover -func=coverage.out
|
||||
testlong:
|
||||
go test pkg/limit/limiter_long_test.go -v
|
||||
test-ui:
|
||||
cd console/atest-ui && npm run test:unit
|
||||
test-e2e:
|
||||
|
|
|
@ -17,8 +17,8 @@ You can install in various methods:
|
|||
|
||||
* CLI via `hd i atest`
|
||||
* Web server
|
||||
* [Kubernetes](https://github.com/LinuxSuRen/api-testing/tree/master/sample/kubernetes)
|
||||
* [Argo CD](https://github.com/LinuxSuRen/api-testing/blob/master/sample/argocd/simple.yaml)
|
||||
* [Kubernetes](https://github.com/LinuxSuRen/api-testing/tree/master/docs/manifests/kubernetes)
|
||||
* [Argo CD](https://github.com/LinuxSuRen/api-testing/blob/master/docs/manifests/argocd/simple.yaml)
|
||||
|
||||
If you're developing APIs locally, the best way is installing it as a container service.
|
||||
Then you can access it via your browser.
|
||||
|
|
|
@ -6,8 +6,7 @@ import (
|
|||
)
|
||||
|
||||
type RateLimiter interface {
|
||||
TryAccept() bool
|
||||
Accept()
|
||||
Accept() bool
|
||||
Stop()
|
||||
Burst() int32
|
||||
}
|
||||
|
@ -28,43 +27,40 @@ func NewDefaultRateLimiter(qps, burst int32) RateLimiter {
|
|||
burst = 5
|
||||
}
|
||||
limiter := &defaultRateLimiter{
|
||||
qps: qps,
|
||||
burst: burst,
|
||||
singal: make(chan struct{}, 1),
|
||||
qps: qps,
|
||||
burst: burst,
|
||||
singal: make(chan struct{}, 1),
|
||||
lastToken: time.Now(),
|
||||
}
|
||||
go limiter.updateBurst()
|
||||
return limiter
|
||||
}
|
||||
|
||||
func (r *defaultRateLimiter) TryAccept() bool {
|
||||
_, ok := r.resver()
|
||||
return ok
|
||||
}
|
||||
|
||||
func (r *defaultRateLimiter) resver() (delay time.Duration, ok bool) {
|
||||
delay = time.Now().Sub(r.lastToken) / time.Millisecond
|
||||
delayRequire := time.Second / time.Duration(r.qps)
|
||||
r.lastToken = time.Now()
|
||||
if delay > 0 {
|
||||
if delay >= delayRequire {
|
||||
ok = true
|
||||
} else if r.Burst() > 0 {
|
||||
r.Setburst(r.Burst() - 1)
|
||||
ok = true
|
||||
} else {
|
||||
delay = time.Second / time.Duration(r.qps)
|
||||
delay = delayRequire - delay
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (r *defaultRateLimiter) Accept() {
|
||||
func (r *defaultRateLimiter) Accept() bool {
|
||||
delay, ok := r.resver()
|
||||
if ok {
|
||||
return
|
||||
return ok
|
||||
}
|
||||
|
||||
if delay > 0 {
|
||||
time.Sleep(delay)
|
||||
}
|
||||
return
|
||||
return ok
|
||||
}
|
||||
|
||||
func (r *defaultRateLimiter) Setburst(burst int32) {
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
//go:build longtest
|
||||
// +build longtest
|
||||
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 API Testing Authors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
package limit_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/linuxsuren/api-testing/pkg/limit"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLimiterWithLongTime(t *testing.T) {
|
||||
for i := 0; i < 10; i++ {
|
||||
testLimiter(t, int32(8+i*2))
|
||||
}
|
||||
}
|
||||
|
||||
func testLimiter(t *testing.T, count int32) {
|
||||
t.Log("test limit with count", count)
|
||||
limiter := limit.NewDefaultRateLimiter(count, 1)
|
||||
num := int32(0)
|
||||
|
||||
loop := true
|
||||
go func(l limit.RateLimiter) {
|
||||
for loop {
|
||||
l.Accept()
|
||||
num += 1
|
||||
}
|
||||
}(limiter)
|
||||
|
||||
select {
|
||||
case <-time.After(time.Second):
|
||||
loop = false
|
||||
}
|
||||
assert.True(t, num <= count+1, num)
|
||||
}
|
|
@ -7,8 +7,9 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestXxx(t *testing.T) {
|
||||
limiter := NewDefaultRateLimiter(1, 1)
|
||||
func TestLimiter(t *testing.T) {
|
||||
t.Log("run rate limit test")
|
||||
limiter := NewDefaultRateLimiter(0, 0)
|
||||
num := 0
|
||||
|
||||
loop := true
|
||||
|
@ -22,6 +23,7 @@ func TestXxx(t *testing.T) {
|
|||
select {
|
||||
case <-time.After(time.Second):
|
||||
loop = false
|
||||
limiter.Stop()
|
||||
}
|
||||
assert.True(t, num <= 10)
|
||||
assert.True(t, num <= 10, num)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue