前言
在编写一个web服务时,我们需要提供接口来来与用户进行交互。那么,无论是出于资源有限还是防止单用户无限请求占用CPU资源,导致服务不可用造成严重后果,对某些重要的接口做限流是非常必要的。
知识点速览
- 什么是限流?
- 限流的粒度?
- 四种经典限流算法:思想固定窗口、滑动窗口、漏桶、令牌桶算法
- 单机限流与多机限流?(单体项目下与分布式项目下) 一些库的实现例如Gava、Redission
什么是限流?
主要是系统为了面对突发的流量处理不过来时,丢弃一些请求来确保服务的持续可用所做的措施。
限流的粒度
- 针对某个有限服务,只允许被其他服务/每个用户调用N次。
- 针对某个接口,只允许在同一时间被调用N次。
- 针对用户的可调用的某个方法,只允许某个用户在某个时间段内调用N次。例如发送短信接口
四种经典限流算法的思想
固定窗口算法
在某个时间间隔内,通过多少请求。
例如:- 1s的间隔内允许5个请求通过
固定窗口算法优缺点
优点
最简单,我们可以只利用一个count计数器,以及startTime、与endTime来做更新。
缺点
可能出现流量突刺
比如:第一个1s间隔内,前0.6s无任何操作,后0.4s秒来了5个请求,而在第二个间隔内,前0.6s来了5个请求,那么在这1s内,就有10个请求,此时是不是不符合限流策略?
滑动窗口算法
单位时间内允许部分操作,但是单位时间是滑动的,需要指定一个滑动单位(例如4s),如下图所示
它的机制是从当前时间的前一个阈值算起,比如说现在是4s,阈值是4s,那么如果在0s - 4s 内的请求超出了预期值,那么此时的请求将会被丢弃。
滑动窗口算法优缺点
优点
滑动窗口算法可以解决固定窗口存在的流量突刺问题,平滑的处理请求。只要是在当前时间-阈值时间 到当前时间内,达到阈值时,更多的操作就会被拒绝。
缺点
实现起来比较复杂,限流的效果和你的滑动单位 有关,滑动的单位越小,限流的效果就会越好,但是实际上我们往往很难选取到一个特别合适的滑动单位,一般都需要结合业务需求。
漏桶算法
该算法以固定的速率去处理请求,当请求打满了桶之后后,拒绝请求。 每秒处理10个请求,桶的容量是10,每0.1秒固定处理一次请求,如果1s内来了10个请求,都可以处理完,但如果1秒内来了11个请求,最后那个请求就会溢出桶,被拒绝
漏桶算法优缺点
优点
能够一定程度上应对流量突刺,固定速率处理请求,保证服务器的安全
缺点
没有办法迅速处理一批请求,只能一个一个按顺序来处理(固定速率的缺点)
令牌桶算法
系统先生成一批令牌,例如每秒生成10个令牌,当用户要操作前,先去拿到一个令牌,有令牌的人就有资格、能同时执行操作。拿不到令牌就阻塞
令牌桶算法的优缺点
优点
能够并发处理同时的请求,并发性能会更高。只要令牌够,在0.1s内处理10个请求都行。
缺点
最大的问题是:时间单位选取很重要。在0.1s内虽然处理了10个请求,不过后续的0.9s的请求都将失败。
限流的实现
限流的实现我们可以直接调用一些函数库
单机限流(本地限流)
可以使用Gava的RateLimite
java
import com.goole.common.util.concurrent.RateLimiter;
public static void main(String[] args){
RateLimiter limiter = RateLimiter.create(5.0);
while(true){
if(limiter.tryAcquire()){
//处理请求
}else{
//超过流量限制,需要的处理方式
}
}
}
多机限流
- 把项目用户的使用频率等数据放到一个集中的存储进行统计,比如Redis,这样无论用户请求落到哪台服务器,都以集中的数据存储内的数据为标准 (Redisson)
- 在网关集中进行限流和统计(比如Sentinel、Spring Cloud Gateway)
java
import org.redisson.Redisson;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
public static void main(String[] args){
//创建RedissonClient
RedissonClient redisson = Redisson.create();
//获取限流器
RSemaphore semaphore = redisson.getSemaphore("mySemaphore");
//尝试获取许可证
boolean result = semaphore.tryAcquire();
if(result){
//处理请求
}else{
//超出流量限制,需要做的处理
}
}
总结
本文介绍了四种经典限流算法,效果较好的是滑动窗口与令牌桶算法。都可以比较好的应对流量突刺问题以及处理效率问题。固定窗口算法最大的缺点是无法处理流量突刺,而漏桶算法则是只能以恒定的速率处理请求。而在实际开发中,我们一定要遵循业务需求,先理解业务再去选择合适的实现方案。