本文主要是介绍漏桶算法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
近期在研究Jaeger,Jaeger中有一种采集策略是速率限制类型,内部使用的是漏桶算法,在这里研究了下Jaeger漏桶算法的实现原理,自己仿照其实现了一个rateLimiter,并进行了相关测试,下面是主要实现。
- lck:lck是互斥锁,主要用来防止并发情况下产生错误。
- rate:速率,即接口每秒限制多少个请求。在这里也就是水滴从漏桶中流出的速度,同时也是余量增加的速度。
- balance:漏桶的空闲余量,会随着漏桶滴水逐渐变大;如果将请求添加到漏桶中,会逐渐变小。当请求到来时,如果余量不足1,那么表明不能容下当前的请求,当前的请求会被拒绝。
- limit:漏桶的最大容量。
- lastTime:上次调用Check函数的时间。用于计算时间差dur,然后计算这段时间漏桶流出的水w,增加的余量=流出的水量w=时间*速率=dur*rate。
rateLimiter实现代码:
package ratelimiterimport ("sync""time"
)type rateLimiter struct {lck *sync.Mutexrate float64 //最大速率限制balance float64 //漏桶的余量limit float64 //漏桶的最大容量限制lastTime time.Time //上次检查的时间
}func NewRateLimiter(limitPerSecond int, balance int) *rateLimiter {return &rateLimiter{lck: new(sync.Mutex),rate: float64(limitPerSecond),balance: float64(balance),limit: float64(balance),lastTime: time.Now(),}
}func (r *rateLimiter) Check() bool {ok := falser.lck.Lock()now := time.Now()dur := now.Sub(r.lastTime).Seconds()r.lastTime = nowwater := dur * r.rate //计算这段时间内漏桶流出水的流量waterr.balance += water //漏桶流出water容量的水,自然漏桶的余量多出waterif r.balance > r.limit {r.balance = r.limit}if r.balance >= 1 { //漏桶余量足够容下当前的请求r.balance -= 1ok = true}r.lck.Unlock()return ok
}
单元测试代码:
package ratelimiterimport ("fmt""testing""time"
)func TestRateLimiter_Check(t *testing.T) {limiter := NewRateLimiter(10, 1)start := time.Now()count := 0for i := 0; i < 1e3; i++ {if limiter.Check() {fmt.Println(i)count++}time.Sleep(time.Millisecond)}fmt.Println("count:", count)fmt.Println(time.Now().Sub(start).Seconds())
}
测试结果:每秒限制10个,1.3秒接受了13个请求,加上一开始填满桶的一个,共14个。
这篇关于漏桶算法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!