电子说
随着系统服务的不断扩展,越来越多的用户访问让我们的系统“不堪重负”,为了防止某些用户恶意高频的访问接口信息,限流(流量限速 Rate Limit)应运而生,这时候选择一个合适的限流算法也就尤为重要。
作者:程造洋
单位:中国移动智慧家庭运营中心智慧互联产品部
Part 01 ● 为什么需要限流呢? ●
大量正常用户高频访问导致服务器宕机
用户恶意高频访问导致服务宕机
网页爬虫
对于这些情况我们需要对用户的访问进行限流访问,限流的目的是保护服务节点或集群底层的存储资源,防止调用方过度使用服务,引起系统崩溃,或者某个调用方过度的使用某个服务,导致其他服务的不可用,为了维持系统的稳定性和可用性,限流刻不容缓。
Part 02 ● 常见的限流算法介绍 ●
2.1 计数器限流
计数器法是限流算法里最简单也是最容易实现的一种算法,具体规则为:在指定周期内累加访问次数,当访问的次数达到我们设定的阈值时,触发限流策略,当进入下一个时间周期时会将访问次数重新清零。
优点:实现简单;
缺点:突刺现象,如果设置每分钟的并发限制数量为100,在单位时间1分钟内的前1s,通过了100个请求,则后面的59s都无法接受任何请求,也就无法应对短时间高并发,存在一定的局限性。
举例:假设有一个恶意用户,他在0:59时,瞬间发送了100个请求,并且1:00又瞬间发送了100个请求,那么其实这个用户在 1秒里面,瞬间发送了200个请求。
我们刚才规定的是1分钟最多100个请求(规划的吞吐量),也就是每秒钟最多1.7个请求,用户通过在时间窗口的重置节点处突发请求, 可以瞬间突破我们的限流限制。用户有可能通过算法的这个漏洞,瞬间压垮我们的应用。
2.2 滑动窗口限流
在了解滑动窗口之前我们需要先了解一下固定窗口,规定:我们单位时间处理的请求数量比如我们规定我们的一个接口一分钟只能访问10次的话。使用固定窗口计数器算法的话可以这样实现:给定一个变量counter来记录处理的请求数量,当1分钟之内处理一个请求之后counter+1,1分钟之内的如果counter=100的话,后续的请求就会被全部拒绝。等到 1分钟结束后,将counter回归成0,重新开始计数。
滑动窗口算是固定窗口计数器算法的升级版。滑动窗口计数器算法相比于固定窗口计数器算法的优化在于:它把时间以一定比例分片。例如我们的借口限流每分钟处理100个请求,我们可以把1 分钟分为100个窗口。每隔1秒移动一次,每个窗口一秒只能处理 不大于100(请求数)/60(窗口数) 的请求, 如果当前窗口的请求计数总和超过了限制的数量的话就不再处理其他请求。滑动方式如下图所示:
很显然,当滑动窗口的格子划分的越多,滑动窗口的滚动就越平滑,限流的统计就会越精确。
2.3 漏桶算法限流
漏桶算法思路很简单:水(请求)先进入到漏桶里,漏桶以一定的速度出水,当水流入速度过大,会在超过桶可接纳的容量时直接溢出。漏桶算法其实很简单,可以粗略的认为就是注水漏水过程,往桶中以任意速率流入水,以一定速率流出水,当水超过桶容量(capacity)则丢弃,因为桶容量是不变的,保证了整体的速率。
优点:削峰,有大量流量进入时,会发生溢出,从而限流保护服务可用;缓冲,不至于直接请求到服务器,缓冲压力;
缺点:漏桶不能有效应对突发流量,但是能起到平滑突发流量(整流)的作用,同时不支持动态扩容。
2.4 令牌桶算法限流
令牌桶算法以一个设定的速率产生令牌并放入令牌桶中,每次请求都得申请令牌,如果令牌数量不足,则拒绝请求。令牌桶算法中新请求到来时会从桶里拿走一个令牌,如果桶内没有令牌可拿,就拒绝服务。当然,令牌的数量也是有上限的。令牌的数量与时间和发放速率强相关,时间流逝的时间越长,会不断往桶里加入越多的令牌,如果令牌发放的速度比申请速度快,令牌桶会放满令牌,直到令牌占满整个令牌桶,如下图所示。
令牌桶限流大致的规则如下:
1)进水口按照某个速度,向桶中放入令牌。
2)令牌的容量是固定的,但是放行的速度不是固定的,只要桶中还有剩余令牌,一旦请求过来就能申请成功,然后放行。
3)如果令牌的发放速度,慢于请求到来速度,桶内就无牌可领,请求就会被拒绝。
优点:可以改变令牌的发放速度,方便应对突发出口流量,是选择较多的限流算法;
缺点:实现复杂,相对于其他限流算法,令牌桶算法的实现较为复杂,对短时请求难以处理,这种情况下,可以考虑使用漏桶算法。
Part 03 ● 常见的限流器,算法库包以及实现方案 ●
滴滴的 tollbooth
Guava RateLimiter限流
轻量级流量控制组件sentinel
redis+lua分布式限流组件
redission分布式限流采用令牌桶思想和固定时间窗口
spring cloud gateway集成redis限流,但属于网关层限流
编辑:黄飞
全部0条评论
快来发表一下你的评论吧 !