01
介绍
为了保护业务系统不会在访问流量过载的情况下出现问题,我们就需要限流。常见的限流算法有:固定时间窗口限流算法,滑动时间窗口限流算法,漏桶限流算法,令牌桶限流算法。其中固定时间窗口限流算法和滑动时间窗口限流算法比较简单,感兴趣的读者可以自己去研究。
02
漏桶
所谓漏桶算法,就像一个漏斗一样,把倒入的水比作访问流量,把流出的水比作业务系统处理的请求,当访问流量过大时,漏桶就会积水,甚至水会溢出。
图片来自网络
推荐 uber 团队开源的一个 Golang 语言实现的关于漏桶限流算法的开源库。
github.com/uber-go/ratelimit
此包提供了漏桶速率限流算法的 Golang 实现。此实现根据请求之间的时间重新填充存储桶,而不是要求间隔时钟离散地填充存储桶。
创建每秒最多执行操作数的限流器。使用时间(1秒)除以设定的每秒最多执行操作数,计算出每个请求之间的时间间隔。每次操作前调用 Take() 方法。判断该请求与上一次请求之间的时间间隔是否达到每个请求之间的间隔时间,如果未达到,Take 就 sleep,直到达到间隔时间才继续执行。
示例代码:
import ( "fmt" "time" "go.uber.org/ratelimit" ) func main() { rl := ratelimit.New(100) // per second prev := time.Now() for i := 0; i < 10; i++ { now := rl.Take() fmt.Println(i, now.Sub(prev)) prev = now } // Output: // 0 0 // 1 10ms // 2 10ms // 3 10ms // 4 10ms // 5 10ms // 6 10ms // 7 10ms // 8 10ms // 9 10ms }
03
令牌桶
所谓令牌桶算法,就是预先放入桶内一些 token,在业务系统处理访问请求时,需要拿到 token 之后才可以处理,如果拿不到 token 就不处理该请求。
图片来自网络
关于令牌桶限流算法,推荐 Github 开源的一个高效的基于令牌桶限流算法实现的限流库:
github.com/juju/ratelimit
关于这个库的文档比较详细,限于篇幅,本文不再介绍使用方法,建议读者直接阅读官方文档。
04
总结
本文我们介绍了常见的几种限流算法,其中重点介绍了漏桶限流算法和令牌桶限流算法,细心的读者可能已经发现,漏桶限流算法是以一个固定的速率处理请求,令牌桶算法是以单位时间内固定处理一定数量的请求,而放入令牌的速度决定了处理请求的平均速度。但是他们也有一个共同点,就是在流量洪峰来临时,他们总是按照自己最大的处理能力来处理访问流量,漏桶是最大容量,令牌桶是最大令牌数量。