漏桶算法

最后更新于:2022-04-02 03:09:14

[TOC] ### 漏桶算法 漏桶算法思路很简单,我们把水比作是`请求`,漏桶比作是`系统处理能力极限`,水先进入到漏桶里,漏桶里的水按一定速率流出,当流出的速率小于流入的速率时,由于漏桶容量有限,后续进入的水直接溢出(拒绝请求),以此实现限流。 它的主要目的是控制数据注入到网络的速率,平滑网络上的突发流量 ![UTOOLS1588125367290.png](http://yanxuan.nosdn.127.net/970d4327b237eae33816ff44b801f2b8.png)
main.go ``` package main import ( "fmt" "math" "sync" "time" ) type LeakyBucket struct { rate float64 //固定每秒出水速率 capacity float64 //桶的容量 water float64 //桶中当前水量 lastLeakMs int64 //桶上次漏水时间戳 ms lock sync.Mutex } func (l *LeakyBucket) Allow() bool { l.lock.Lock() defer l.lock.Unlock() now := time.Now().UnixNano() / 1e6 eclipse := float64(now - l.lastLeakMs) * l.rate / 1000 //先执行漏水 l.water = l.water - eclipse //计算剩余水量 l.water = math.Max(0, l.water) //桶干了 l.lastLeakMs = now if (l.water + 1) < l.capacity { // 尝试加水,并且水还未满 l.water++ return true } else { // 水满,拒绝加水 return false } } func (l *LeakyBucket) Set(r, c float64) { l.rate = r l.capacity = c l.water = 0 l.lastLeakMs = time.Now().UnixNano() / 1e6 } func main() { var leak LeakyBucket leak.Set(5,100) for i:=0; i<100000; i++ { if leak.Allow() { fmt.Printf("%+v s,i=%d\n", i/100,i ) }else if i%100==0 { fmt.Printf("%+v s\n", i/100 ) } time.Sleep(1*time.Millisecond) } } ```

**特点**: - 漏桶具有固定容量,出水速率是固定常量(流出请求) - 如果桶是空的,则不需流出水滴 - 可以以任意速率流入水滴到漏桶(流入请求) - 如果流入水滴超出了桶的容量,则流入的水滴溢出(新请求被拒绝) 漏桶限制的是常量流出速率(即流出速率是一个固定常量值),所以最大的速率就是出水的速率,不能出现突发流量 **缺陷**: 漏桶算法不能够有效地使用网络资源。因为漏桶的漏出速率是固定的参数,漏桶算法对于存在突发特性的流量来说缺乏效率
';