go-zero 是如何实现令牌桶限流的?
上一篇文章介绍了 如何实现计数器限流?主要有两种实现方式,分别是固定窗口和滑动窗口,并且分析了 go-zero 采用固定窗口方式实现的源码。
但是采用固定窗口实现的限流器会有两个问题:
会出现请求量超出限制值两倍的情况
无法很好处理流量突增问题
这篇文章来介绍一下令牌桶算法,可以很好解决以上两个问题。
工作原理
算法概念如下:
令牌以固定速率生成;
生成的令牌放入令牌桶中存放,如果令牌桶满了则多余的令牌会直接丢弃,当请求到达时,会尝试从令牌桶中取令牌,取到了令牌的请求可以执行;
如果桶空了,那么尝试取令牌的请求会被直接丢弃。
![](https://static001.geekbang.org/infoq/fd/fd2c4f5bcdfe2102f6c31fea2aa7414e.png)
令牌桶算法既能够将所有的请求平均分布到时间区间内,又能接受服务器能够承受范围内的突发请求,因此是目前使用较为广泛的一种限流算法。
源码实现
源码分析我们还是以 go-zero 项目为例,首先来看生成令牌的部分,依然是使用 Redis 来实现。
Redis 中主要保存两个 key,分别是 token 数量和刷新时间。
核心思想就是比较两次请求时间间隔内生成的 token 数量 + 桶内剩余 token 数量,和请求量之间的大小,如果满足则允许,否则则不允许。
限流器初始化:
其中有一个变量 rescueLimiter
,这是一个进程内的限流器。如果 Redis 发生故障了,那么就使用这个,算是一个保障,尽量避免系统被突发流量拖垮。
![](https://static001.geekbang.org/infoq/d1/d131dc3951d12b923d26d3fa4010dad6.png)
提供了四个可调用方法:
最终调用的都是 reverveN
方法:
最后看一下进程内限流的启动与恢复:
以上就是本文的全部内容,如果觉得还不错的话欢迎点赞,转发和关注,感谢支持。
参考文章:
https://juejin.cn/post/7052171117116522504
https://www.infoq.cn/article/Qg2tX8fyw5Vt-f3HH673
推荐阅读:
版权声明: 本文为 InfoQ 作者【AlwaysBeta】的原创文章。
原文链接:【http://xie.infoq.cn/article/f0857935120d506f733ea875b】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论