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

前言

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

总结

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

相关推荐
代码吐槽菌1 小时前
基于SSM的毕业论文管理系统【附源码】
java·开发语言·数据库·后端·ssm
ZOMI酱2 小时前
【AI系统】GPU 架构与 CUDA 关系
人工智能·架构
豌豆花下猫2 小时前
Python 潮流周刊#78:async/await 是糟糕的设计(摘要)
后端·python·ai
YMWM_2 小时前
第一章 Go语言简介
开发语言·后端·golang
码蜂窝编程官方2 小时前
【含开题报告+文档+PPT+源码】基于SpringBoot+Vue的虎鲸旅游攻略网的设计与实现
java·vue.js·spring boot·后端·spring·旅游
hummhumm2 小时前
第 25 章 - Golang 项目结构
java·开发语言·前端·后端·python·elasticsearch·golang
J老熊2 小时前
JavaFX:简介、使用场景、常见问题及对比其他框架分析
java·开发语言·后端·面试·系统架构·软件工程
AuroraI'ncoding3 小时前
时间请求参数、响应
java·后端·spring
好奇的菜鸟3 小时前
Go语言中的引用类型:指针与传递机制
开发语言·后端·golang
Alive~o.03 小时前
Go语言进阶&依赖管理
开发语言·后端·golang