Merge pull request #17673 from hongchaodeng/metrics

Auto commit by PR queue bot
This commit is contained in:
k8s-merge-robot
2015-12-05 05:30:08 -08:00
7 changed files with 91 additions and 7 deletions

View File

@@ -26,9 +26,14 @@ type RateLimiter interface {
Accept()
// Stop stops the rate limiter, subsequent calls to CanAccept will return false
Stop()
// Saturation returns a percentage number which describes how saturated
// this rate limiter is.
// Usually we use token bucket rate limiter. In that case,
// 1.0 means no tokens are available; 0.0 means we have a full bucket of tokens to use.
Saturation() float64
}
type tickRateLimiter struct {
type tokenBucketRateLimiter struct {
limiter *ratelimit.Bucket
}
@@ -39,7 +44,7 @@ type tickRateLimiter struct {
// The maximum number of tokens in the bucket is capped at 'burst'.
func NewTokenBucketRateLimiter(qps float32, burst int) RateLimiter {
limiter := ratelimit.NewBucketWithRate(float64(qps), int64(burst))
return &tickRateLimiter{limiter}
return &tokenBucketRateLimiter{limiter}
}
type fakeRateLimiter struct{}
@@ -48,22 +53,32 @@ func NewFakeRateLimiter() RateLimiter {
return &fakeRateLimiter{}
}
func (t *tickRateLimiter) TryAccept() bool {
func (t *tokenBucketRateLimiter) TryAccept() bool {
return t.limiter.TakeAvailable(1) == 1
}
func (t *tokenBucketRateLimiter) Saturation() float64 {
capacity := t.limiter.Capacity()
avail := t.limiter.Available()
return float64(capacity-avail) / float64(capacity)
}
// Accept will block until a token becomes available
func (t *tickRateLimiter) Accept() {
func (t *tokenBucketRateLimiter) Accept() {
t.limiter.Wait(1)
}
func (t *tickRateLimiter) Stop() {
func (t *tokenBucketRateLimiter) Stop() {
}
func (t *fakeRateLimiter) TryAccept() bool {
return true
}
func (t *fakeRateLimiter) Saturation() float64 {
return 0
}
func (t *fakeRateLimiter) Stop() {}
func (t *fakeRateLimiter) Accept() {}

View File

@@ -17,6 +17,7 @@ limitations under the License.
package util
import (
"math"
"testing"
"time"
)
@@ -63,3 +64,26 @@ func TestThrottle(t *testing.T) {
t.Error("rate limit was not respected, finished too early")
}
}
func TestRateLimiterSaturation(t *testing.T) {
const e = 0.000001
tests := []struct {
capacity int
take int
expectedSaturation float64
}{
{1, 1, 1},
{10, 3, 0.3},
}
for i, tt := range tests {
rl := NewTokenBucketRateLimiter(1, tt.capacity)
for i := 0; i < tt.take; i++ {
rl.Accept()
}
if math.Abs(rl.Saturation()-tt.expectedSaturation) > e {
t.Fatalf("#%d: Saturation rate difference isn't within tolerable range\n want=%f, get=%f",
i, tt.expectedSaturation, rl.Saturation())
}
}
}