限流,是服务或者应用对自身保护的一种手段,通过限制或者拒绝调用方的流量,来保证自身的负载。
常用的限流算法有两种:漏桶算法和令牌桶算法
漏桶算法
思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水,当水流入速度过大会直接溢出,可以看出漏桶算法能强行限制数据的传输速率。
对于很多应用场景来说,除了要求能够限制数据的平均传输速率外,还要求允许某种程度的突发传输。这时候漏桶算法可能就不合适了,令牌桶算法更为适合。
令牌桶算法
原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。
下面的内容主要讨论令牌桶算法。
仔细讨论之前,先看下一下基于分布式缓存实现的令牌桶的流程图。
以下是对流程图的讲解:
1. key是否存在。因为流程图是基于分布式缓存做的集群限流,需要根据不同key做统计,第一次访问初始化key。
2. 如果key不存在,初始化令牌桶,防止初始令牌数量,并且设置key过期时间为interval*2。这里的初始令牌数量一般可以设置成限流阈值,比如限流10qps,初始值可以设置成10,来应对一开始的流量。interval是间隔时间,比如限流阈值10qps,interval设置为1s。过期时间是缓存中key的时间,interval*2是为了防止key过期无法拦截流量。
3. 如果key存在,将当前请求时间和当前key的最后放置令牌时间做比较。如果间隔超过interval,进入第4步,间隔未超过interval,进入第5步。
4. 间隔已经超过1s,直接放置令牌到最大数量。
5. 间隔没有超过1s,定义delta为时间差,放置令牌数=delta/(1/qps)。放入令牌时保证令牌数不超过桶的容量。同时,重置放入令牌的时间。
6. 从桶中获取令牌,获取令牌成功,执行请求;获取令牌时间,拒绝请求。
以上是对令牌桶算法的一种实现,