分布式限流算法及实现介绍

news2024/11/29 9:55:34

分布式系统架构下面对突增的高并发访问请求,如何实现限流以保护系统的可用性是需要关注的一个问题。分布式限流实现机制上有很多中,包括基于网关实现、基于中间件如Redis实现等,本文简要介绍限流的常用算法以及实现方案。


1、分布式限流概述

所谓“限流”是在高并发业务场景下,超过系统处理能力后,为确保系统稳定性和可用性所采取的技术手段。比如12306抢火车票的验证码图片,双十一等秒杀活动下的排队处理等,各个技术厂商的限流手段也是层出不穷。在现实生活中的限流也很常见,比如高峰期的地铁限流、黄金周的景区限流,还有疫情高峰期的排队核酸等。
在这里插入图片描述

在分布式系统中,面对大数据量的高并发访问请求时,可能有多个服务节点协同工作,每个节点可能会处理多个请求。因此,需要一种方法来控制每个请求的访问频率,以避免过多的请求导致系统负载过高或崩溃。常用的技术手段就是限流,限流其实就是在某个时间窗口对资源访问的限制,而分布式限流就是将整个分布式环境当一个整体来考量,当达到请求数或者并发限制后,就进行等待、排队、降级或者拒绝服务等限制。

1.1 分布式限流规则

限流通常是对时间和资源两个维度的限制:1)基于特定的时间窗口比如每分钟、每秒钟限制;2)基于可用资源的限制比如设定最大访问次数或连接数。

在这里插入图片描述

在实际的使用场景中会基于多个规则进行限制,常见的限流规则如下:

  1. 基于QPS和连接数控制:根据每个节点的QPS和连接数来设定限流值,如果某个节点的请求量超过了限流值,则拒绝该请求。
  2. 基于传输速率限制:通过限制每个请求的传输速率来控制请求的速率,如果传输速率超过了限制,则拒绝请求。
  3. 基于IP纬度限制:根据每个请求的IP地址进行限流,如果多个请求的IP地址属于同一个子网,则按照同一个限流规则进行限流。
  4. 基于服务器限制:根据每个请求所访问的服务器来进行限流,如果多个请求访问了同一台服务器,则按照同一个限流规则进行限流。
  5. 黑白名单限制:将拒绝请求的理由设置为黑名单,将允许请求的理由设置为白名单。黑名单可以根据实际需求进行设置,白名单可以从配置文件或用户输入中获取。

在实际业务场景使用过程中,需要根据具体情况进行调整和优化,以确保分布式限流算法能够满足实际需求,提高系统的性能和可用性。

1.2 分布式限流方案

分布式限流的主流方案包括从用户客户端限流、服务网关层实现限流以及基于中间件或限流组件实现限流。

  1. 客户端限流:类似于12306抢票的验证码限制,通过在前端增加验证访问达到限制流量的目的,从而大幅度降低系统的访问压力。
  2. 网关层限流策略:在分布式系统中,服务网关作为分布式链路的第一道关卡,承接了所有的用户请求。如图所示,从服务网关层->后端服务->后端缓存->数据库层,整个流量访问是一个漏斗型,在网关层做好流量的控制后,将极大的降低后端服务层的压力。常用的网关实现可以使用Nginx、Spring Cloud Gateway等。

在这里插入图片描述

  1. 基于中间件的限流策略:网关层的限流措施对后端业务来说无法控制,因此可以使用中间件比如Redis实现服务层的限流策略,利用Redis脚本化编程能力将限流模块和业务功能解耦,以及Redis高并发特性和高可用架构实现稳定的中间件层限流机制。
  2. 基于限流组件实现限流:一些开源的限流组件如阿里的Sentinel可以实现限流功能

2、分布式限流常用算法介绍

无论是网关层限流,还是基于中间件层的实现,具体的分布式限流算法无外乎以下几种:

  1. 计数器限流算法:在有效时间内计算请求次数,调用一次+1,调用结束-1。可以使用Redis的incr或其他计数工具实现。
  2. 滑动窗口限流算法:每过一个步长,整体时间区域滑动一下,以滑动窗口的机制减少临界值带来的超过阈值的问题。
  3. 漏桶限流算法:恒定速率的限流算法,不论客户端请求量是多少,服务端处理请求的速度都是恒定的。
  4. 令牌桶限流算法:有一个令牌桶和定时器,在一个时间段内往令牌桶里生成固定数量的令牌,请求就从桶里拿一个令牌,如果令牌没了,就排队或拒绝服务。
2.1 计数器限流算法

计数器限流算法是一种简单而有效的限流方案,它通过为每个请求分配一个计数器,当计数器达到一定值时,限制请求的处理速率或拒绝请求。这种方案简单易实现,但可能会出现限流不够精准的情况。

实现计数器限流算法的步骤如下:

  • 设置一个计数器count,接收一个请求就将计数器加一,同时记录当前时间。
  • 判断当前时间和上次统计时间是否为同一分钟。如果是,则判断count是否超过阈值,如果超过阈值,则返回限流拒绝。如果不是,则把count重置为1。

在这里插入图片描述

计数器限流算法存在的问题是当跨窗口的时间范围内的统计数据超出阈值,比如T-1m时候请求为100,T+1m是请求也是100,相当于2分钟内请求达到200,出现请求毛刺现象,显然是不满足限流的要求的。为解决这个问题,产生了滑动窗口限流算法。

2.2 滑动窗口限流算法

滑动窗口限流算法是一种基于窗口的限流方案,它通过维护一个滑动窗口来限制请求的处理速率。该算法的基本思路是将请求按照时间顺序分配到不同的窗口中,每个窗口内的请求数量可以根据实际需求进行调整。当某个窗口内的请求数量达到限制值时,限制请求的处理速率或拒绝请求。流量经过滑动时间窗口算法整形之后,可以保证任意时间窗口内,都不会超过最大允许的限流值,从流量曲线上来看会更加平滑,可以部分解决上面提到的临界突发流量问题。

实现滑动窗口限流算法的步骤如下:

  • 初始化请求计数器count,窗口大小size,以及滑动窗口window。
  • 接收一个请求,计算请求的时间delta,将请求分配到相应的窗口中。
  • 更新窗口大小size,将window向右移动一个位置,并重新计算窗口内的请求数量。
  • 如果请求数量超过限制值,则限制请求的处理速率或拒绝请求。

在这里插入图片描述

如图所示,如果在临界收到100个请求,在下一个窗口来临时又接收新的请求过来,但是整个滑动窗口内的请求已经达到上线,不再接受新的请求。

2.3 漏桶限流算法

漏桶(Leaky Bucket)限流算法可以理解为注水漏水的过程,往漏桶中以任意速率流入水,以固定的速率流出水。当水超过桶的容量时,会被溢出,也就是被丢弃。因为桶容量是不变的,保证了整体的速率。漏桶是将请求放入桶中,如果桶满了,后面来的数据包将会被丢失。

  • 流入的水滴,可以看作是访问系统的请求,这个流入速率是不确定的;
  • 桶的容量一般用来表示系统所能处理的请求数。如果桶的容量满了,也就达到限流的阀值,会丢弃水滴(即:拒绝请求);
  • 流出的水滴,是恒定速率的,用来表示服务按照固定的速率处理请求。

在这里插入图片描述

漏桶限流算法的主要步骤:

  1. 初始化:定义桶的容量和漏桶的流出速率。
  2. 漏桶缓存:当有请求到达时,如果桶的容量未达到上限,直接接受该请求;否则,将该请求放入漏桶中等待处理。
  3. 处理漏桶中的请求:定时从漏桶中取出待处理的请求,以恒定的速率进行处理,直到漏桶为空。
  4. 外部请求处理:如果外部请求数量超过了系统的处理能力,需要对请求进行限流,防止系统过载。
  5. 启动时流量平缓:如果想让系统有一个陆续启动的过程,则不用一下子接受太多请求,让系统处理请求量平缓上升到最大处理能力。

需要注意的是,漏桶算法的优点是可以保证处理速度恒定,缺点是无法应对突发流量。因此,通常需要结合其他算法使用,以实现更灵活和高效的限流策略。

2.4 令牌桶限流算法

令牌桶(Token Bucket)算法是对漏桶算法的一种改进,不仅能够平滑限流,还允许一定程度的流量突发。

  1. 令牌:只有获得到令牌的Request请求才会被处理,其他Request请求要么排队要么被直接丢弃
  2. 桶:用来装令牌的地方,所有Request都从这个桶里获取令牌

在这里插入图片描述

令牌桶限流算法的实现主要包括以下步骤:

  1. 定义令牌桶的容量和令牌的释放速率:令牌桶的容量和令牌的释放速率表示流量控制的强度。令牌桶的容量代表桶中最多能存储的令牌数量,令牌的释放速率代表每单位时间(如每秒)释放的令牌数。可以根据实际需求调整令牌桶的容量和令牌的释放速率。
  2. 往令牌桶中添加令牌:如果有流量需要发送或请求,需要先到令牌桶中获取令牌。如果令牌桶中还有令牌,则流量可以被发送或请求。如果令牌桶已经达到桶的容量,则新的流量将被拒绝。
  3. 维护令牌桶中的令牌数量:为了实现动态调整流量控制强度,需要定时往令牌桶中添加新的令牌。同时,也需要定时检查令牌桶中的令牌数量,并将超过一定数量的令牌丢弃。
  4. 对拒绝的请求或数据流量进行处理:当拒绝新的请求或数据流量时,需要采取一些措施来处理被拒绝的请求或数据流量。例如,可以返回超时错误或重试机制等。

令牌桶限流算法的优点包括可以应对突发流量和公平性,即所有请求或数据流量都按照相同的速率被控制,不会出现有时通过很快、有时很慢的情况。缺点在于需要对令牌的数量和释放速率进行动态调整,以适应不同的网络环境和流量特征。因此,与漏桶限流算法相比,令牌桶限流算法更适用于复杂的流量控制场景。

3、分布式限流实现方案

3.1 使用Nginx实现

Nginx可以使用类似限流器的模块实现分布式限流,可以在每个进程或子进程上限制每个连接的访问速率或者控制并发连接数。下面是使用Nginx和ratelimit模块实现分布式限流的简单示例:

1) 控制速率

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s;
  • $binary_remote_addr表示通过remote_addr这个标识来做限制,“binary_”的目的是缩写内存占用量,是限制同一客户端ip地址。
  • zone=mylimit:10m表示生成一个大小为10M,名字为one的内存区域,用来存储访问的频次信息。
  • rate=2r/s表示允许相同标识的客户端的访问频次,这里限制的是每秒2次,还可以有比如30r/m的。

2)控制并发连接数

 #统一在http域中进行配置
 #限制请求
 limit_req_zone $uri zone=api_read:20m rate=50r/s;

 #按ip配置一个连接 zone
 limit_conn_zone $binary_remote_addr zone=perip_conn:10m;

 #按server配置一个连接 zone
 limit_conn_zone $server_name zone=perserver_conn:100m;
 
===== server =====
location / {
 if (!-e $request_filename){
  rewrite ^/(.*) /index.php last;
 }
 
 #请求限流排队通过 burst默认是0
 limit_req zone=api_read burst=100;
 
 #连接数限制,每个IP并发请求为50
 limit_conn perip_conn 50;
 
 #服务所限制的连接数(即限制了该server并发连接数量)
 limit_conn perserver_conn 200;
 
 #连接限速
 #limit_rate 100k;
}

限流配置参数如下:

  • rate=50r/s:每秒新增50个令牌
  • burst=100:令牌桶一共有100个令牌
  • perip_conn 50:每个IP最多并发50个连接
  • perserver_conn 200:限制该server并发连接数
3.2 使用Redis实现

1)Redis+Lua脚本实现限流

Redis+Lua脚本可用于实现高并发和高性能的流量限制

-- 获取调用脚本时传入的第一个key值(用作限流的 key)
local key = KEYS[1]
-- 获取调用脚本时传入的第一个参数值(限流大小)
local limit = tonumber(ARGV[1])
 
-- 获取当前流量大小
-- (redis.call方法,从缓存中get和key相关的值,如果为null那么就返回0)
local curentLimit = tonumber(redis.call('get', key) or "0")
 
-- 判断缓存中记录的数值是否会大于限制大小,如果超出表示该被限流,返回0
-- 如果未超过,那么该key的缓存值+1,并设置过期时间,并返回缓存值+1
 
-- 是否超出限流(如果超出限流大小,直接返回)
if curentLimit + 1 > limit then
    return 0
else
    redis.call("INCRBY", key, 1) -- 没有超出 value + 1(请求数+1)
    redis.call("EXPIRE", key, 2) -- 设置过期时间(设置2秒过期)
    return 1 -- 放行请求
end

2)Redis实现令牌桶算法

每次访问请求时都可以从Redis获取令牌,当令牌桶中没有可用令牌时,请求则被拒绝。详细流程如下:

  1. 初始化令牌桶:在Redis中创建一个新键,例如“rate_limiter:myapp”,该键的值应该是一个有序集合。
  2. 添加令牌:在Redis中使用INCRBY命令对“rate_limiter:myapp”键的值进行自增,例如INCRBY 1。这将在有序集合中添加一个令牌。
  3. 获取令牌:在Redis中使用GET命令获取“rate_limiter:myapp”键的值,例如GET “rate_limiter:myapp”。这将返回有序集合中的令牌数量。
  4. 判断是否限流:如果获取的令牌数量大于等于令牌桶容量,则表示令牌桶已满,需要限流。否则,表示令牌桶未满,可以继续处理请求。
  5. 限流处理:如果需要限流,在Redis中使用LPOP命令从有序集合的左侧弹出一个令牌,例如LPOP “rate_limiter:myapp”。这将从有序集合中删除一个令牌,并返回被删除的令牌。在限流处理中,可以将被删除的令牌与客户端请求一起返回,以告诉客户端需要等待多长时间才能再次发送请求。
  6. 添加过期时间:为了防止因为Redis宕机而导致令牌桶中的令牌一直增加而没有上限,需要为有序集合添加一个过期时间。可以将过期时间设置为限流速率(即每秒添加的令牌数),例如“rate_limiter:myapp”键的过期时间可以设置为1秒。这样,即使Redis宕机,每隔1秒也会有一个新的令牌添加到有序集合中,从而保证有序集合中的令牌数量不会超过令牌桶容量。
  7. 重新初始化:如果需要重新开始限流,可以使用DEL命令删除“rate_limiter:myapp”键,并重新初始化令牌桶。
3.3 使用Spring Cloud Gateway实现

Spring cloud gateway提供了一个自实现的限流过滤器RequestRateLimiterGatewayFilterFactory,这个过滤器里面有两个参数:一个是KeyResolver,还有一个是RateLimiter,采用的是令牌桶算法实现。

1)配置Redis和限流信息

- id: server2
 uri: lb://eureka-server1
 predicates:
   - Path=/server1/test
 filters:
   - name: RequestRateLimiter
     args:
      key-resolver: "#{@hostAddrKeyResolver}"
      redis-rate-limiter.replenishRate: 1 # 令牌桶填充的速率 秒为单位
      redis-rate-limiter.burstCapacity: 1 # 令牌桶总容量
      redis-rate-limiter.requestedTokens: 1 # 每次请求获取的令牌数

配置参数:令牌生成的速率是1/s,令牌桶的总容量也为1,每次请求获取一个令牌。也就是一秒只允许一次请求。


参考资料:

  1. https://blog.csdn.net/tanwei010915/article/details/122489227
  2. https://blog.csdn.net/qq_38584262/article/details/108273978
  3. https://blog.csdn.net/kansting/article/details/126560538
  4. https://blog.csdn.net/tanwei010915/article/details/122489227

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/626340.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows操作系统渗透测试

Windows操作系统渗透测试 任务环境说明:服务器场景名:Server02服务器场景操作系统:未知(关闭链接) 1.通过本地PC中渗透测试平台Kali对服务器场景进行系统服务及版本扫描渗透测试,并将该操作显示结果中808…

可视化报表系统推荐

在当今信息时代,数据的处理和分析已经成为了企业管理中不可或缺的一部分。而报表则是这个过程中最常见的工具之一。手工写报表虽然简单易懂,但是随着数据量的增加,这种方式逐渐暴露出许多痛点。比如说: 1.时间耗费长:…

Linux之进程间通信——管道

文章目录 前言一、进程间通信1.概念2.目的3.进程间通信分类 二、管道1.管道介绍2.管道分类1.匿名管道pipi创建管道文件,打开读写端fork子进程关闭父进程的读取端,关闭子进程的写入端读写特征管道特征 2.命名管道mkfifo创建管道文件删除管道文件通信 三、…

【openframework】实时路径规划(RTRRTstar算法)

程序框架 视频演示 实时RRT-star算法介绍 实时RRT-star算法是一种基于采样的运动规划算法,它可以在有限的时间内找到一条渐进最优的路径。实时RRT-star算法是在RRT-star算法的基础上进行了改进,主要有两个方面: - 实时更新起始点。实时RRT-st…

那些漏洞挖掘高手都是怎么挖漏洞的?

前言 说到安全就不能不说漏洞,而说到漏洞就不可避免地会说到三座大山: 漏洞分析 漏洞利用 漏洞挖掘 从个人的感觉上来看,这三者尽管通常水乳交融、相互依赖,但难度是不尽相同的。本文就这三者分别谈谈自己的经验和想法。 漏洞分析…

Mac图片批处理工具

PhotoMill X是一款强大的图像处理软件,它可以帮助用户快速地对照片进行编辑、调整和转换。它支持在单个或批量模式下处理大量的图像文件,并具有直观的用户界面和易于使用的工具。 PhotoMill X具有广泛的编辑功能,包括裁剪、缩放、旋转、调整明…

记录基于Vue.js的Tree组件_Liquor Tree

酒树 (Liquor Tree) A Vue tree component that allows you to present hierarchically organized data in a nice and logical manner. Vue 树组件,可让您以美观和逻辑的方式呈现层次结构的数据。 supports mobile, and has a variety of response events. Flex…

软考A计划-电子商务设计师-模拟试题卷三

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分享&am…

springboot+websocket客服聊天

续&#xff1a;spring boot 完整后端接口案例_cc&的博客-CSDN博客 后台代码 1.在pom.xml中添加spring-boot-starter-websocket <!--WebSocket--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter…

浅谈数明深力科隔离驱动器SLMi8235BD 车载充电器(OBC)方案

数明深力科SLMi823x系列SLMi8235BD隔离驱动技术优势&#xff1a;具有高性能、高性价比、高可靠性的产品特性&#xff0c;应用覆盖UPS、充电桩、服务器电源、通信电源、新能源汽车动力总成系统的车载 OBC 领域。通过CQC认证的。 车载充电器&#xff08;OBC&#xff09;是电动汽…

在线电子书创建:MkDocs + Github + ReadTheDocs

MkDocs是一个静态站点生成器&#xff0c;可用于构建项目文档。文档文件使用Markdown语法编写&#xff0c;本文记录如何使用MkDocs生成项目文档&#xff0c;并部署到Read the Docs上。 目录 安装mkdocs搭建文档项目创建项目启动项目编写文档Markdown语法站内链接图片 文档结构 配…

聚观早报 | 苹果收购AR头显初创公司Mira;抖音将尝试自营电商

今日要闻&#xff1a;苹果收购AR头显初创公司Mira&#xff1b;抖音将尝试自营电商&#xff1b;特斯拉股价实现九连涨&#xff1b;《黑镜》主创曾试用ChatGPT写剧本&#xff1b;携程集团发布2023Q1财报 苹果收购AR头显初创公司Mira 6 月 7 日消息&#xff0c;据 The Verge 报道…

2023免费电脑录视频软件Camtasia

Camtasia 2023是专业又好用的录屏软件&#xff0c;既可以用来录视频、ppt、直播课程等&#xff0c;也能够处理视频&#xff0c;添加各种效果&#xff0c;制作出更加满意的视频作品。Camtasia凭借愈发强大的功能收获了一大批忠实用户和如潮好评&#xff0c;已成为屏幕录制的必备…

6.16 @ 广州丨相约泛娱乐出海论坛,探寻市场突围的核心要义

1979 年&#xff0c;“出国办企业”第一次被有关部门提出&#xff0c;开启了中国企业对外投资的积极探索与尝试。经过 40 多年的耕耘&#xff0c;不少出海品牌已经站稳了脚跟&#xff0c;品牌影响力与日俱增&#xff0c;甚至在部分核心细分赛道上&#xff0c;中国企业凸显出了明…

TiDB 7.1 LTS 发版:为关键业务提供业务稳定性和多租户场景支持

近日&#xff0c;企业级开源分布式数据库厂商 PingCAP 正式发布 TiDB 7.1 版本&#xff0c;这也是 2023 年度发布的首个 LTS&#xff08;Long Term Support&#xff09; 版本&#xff0c;汇集了来自 20 个真实场景带来的功能增强&#xff0c;累计优化和修复 140 功能&#xff0…

easyui5

1.1准备工作. 今天我们的主要任务是完成分页功能&#xff1b; 导入数据表 t_book&#xff0c;数据文件在课件&#xff1b; 介绍拼音字段&#xff0c;拼音工具类&#xff0c;拼音jar包&#xff1b; 模糊查询还要实现拼音模糊查询&#xff0c;如&#xff1a;百度输入拼音也可以…

飞凌嵌入式AM62x系列核心板配置新增,单核/双核/四核随心选

新时代&#xff0c;工业、电力、交通、医疗等众多行业纷纷从信息化向着智能化转型&#xff0c;这就对主控的综合性能提出了全新的要求。在这样的背景下 TI AM62x Sitara™处理器应运而生&#xff0c;为AIoT时代带来了新的突破可能。作为TI官方合作伙伴&#xff0c;飞凌嵌入式于…

RabbitMQ - 发布确认高级

RabbitMQ - 发布确认高级 发布确认 springboot 版本回退消息备份交换机 在生产环境中由于一些不明原因&#xff0c;导致 RabbitMQ 重启&#xff0c;在 RabbitMQ 重启期间生产者消息投递失败&#xff0c; 导致消息丢失&#xff0c;需要手动处理和恢复。于是&#xff0c;我们开始…

Steemit 会颠覆 Quora/知乎 甚至 Facebook 吗?

Steemit是基于区块链技术的社交媒体平台&#xff0c;其独特的激励机制吸引了众多用户。然而&#xff0c;是否能够真正颠覆Quora、知乎甚至Facebook这些已经成为社交巨头的平台&#xff0c;仍然存在着许多未知因素。本文将探讨Steemit的优势和挑战&#xff0c;以及其在社交领域中…

数据分析第15课pandas和matplotlib实战

01实战:911 导入: 读取数据: 转换类型: