开发必备:接口的限流思想总结

前言

在编写一个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{
		//超出流量限制,需要做的处理
	}
}

总结

本文介绍了四种经典限流算法,效果较好的是滑动窗口与令牌桶算法。都可以比较好的应对流量突刺问题以及处理效率问题。固定窗口算法最大的缺点是无法处理流量突刺,而漏桶算法则是只能以恒定的速率处理请求。而在实际开发中,我们一定要遵循业务需求,先理解业务再去选择合适的实现方案。

相关推荐
Asthenia04122 分钟前
详细分析:ConcurrentLinkedQueue
后端
uhakadotcom12 分钟前
Ruff:Python 代码分析工具的新选择
后端·面试·github
uhakadotcom15 分钟前
Mypy入门:Python静态类型检查工具
后端·面试·github
喵个咪21 分钟前
开箱即用的GO后台管理系统 Kratos Admin - 定时任务
后端·微服务·消息队列
Asthenia041223 分钟前
ArrayList与LinkedList源码分析及面试应对策略
后端
Asthenia04121 小时前
由浅入深解析Redis事务机制及其业务应用-电商场景解决超卖
后端
Asthenia04121 小时前
Redis详解:从内存一致性到持久化策略的思维链条
后端
Asthenia04121 小时前
深入剖析 Redis 持久化:RDB 与 AOF 的全景解析
后端
Apifox1 小时前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
掘金一周1 小时前
金石焕新程 >> 瓜分万元现金大奖征文活动即将回归 | 掘金一周 4.3
前端·人工智能·后端