限流器
限流器的主要作用是控制流量,保护系统不会在过载情况下出现问题。
比如在某些场景下,当并发访问量陡增时,可能会给系统带来毁灭性打击,继而引起系统雪崩,导致服务不可用。比如在一些秒杀,抢票的场景,在一些评论、下单的场景,我们可以根据每个场景的特点来定制适合的限流方案,即使出现高并发的时候,也能正常服务或有损服务,不至于服务挂掉。
一般的应用场景有:
防止恶意请求流量
防止恶意攻击
防止流量超出系统峰值
限流的一般方式有:
限制总并发数(如数据库连接池、线程池等)
限制瞬时并发数(如Nginx 的 limit_conn 等)
限制时间窗口内的平均速率(如Guava 的 RateLimiter、Nginx 的 limit_req 等)
限制远程接口调用速率
限制 MQ 的消费速率
限制每秒平均速率
当然限流不是目的,一旦达到了限流的阈值,就会触发相应的限流行为。比如:
拒绝服务
服务降级
特权请求
延时处理
弹性伸缩
限流器算法
限流有一些常用的限流算法,也有很多类库封装了这些算法。
计数法
算法思想:维护一个计数器,当一个请求来时,就做加1操作,当一个请求处理完成时,就做减1操作;如果这个 Counter 大于某个数了(我们设定的限流阈值),那么就开始拒绝请求以保护系统的负载了。
这个算法简单粗暴。
但是这种方法存在缺点:不能均衡限流,在一个单位时间的末尾和下一个单位时间的开始,很可能会有两个访问的峰值,导致系统崩溃。
滑动窗口法
令牌桶法
令牌桶算法的详细描述如下:
令牌以固定的速率添加到令牌桶中,假设限流的速率是 r/ 秒,则令牌每 1/r 秒会添加一个;
假设令牌桶的容量是 b ,如果令牌桶已满,则新的令牌会被丢弃;
请求能够通过限流器的前提是令牌桶中有令牌。
漏桶法
漏桶(Leaky Bucket)算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水(接口有响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请求,可以看出漏桶算法能强行限制数据的传输速率。
一般来说,这个“漏斗”是用一个队列来实现的,当请求过多时,队列就会开始积压请求,如果队列满了,就会开拒绝请求。很多系统都有这样的设计,比如 TCP。当请求的数量过多时,就会有一个 sync backlog 的队列来缓冲请求,或是 TCP 的滑动窗口也是用于流控的队列。漏斗算法其实就是在队列请求中加上一个限流器,来让 Processor 以一个均匀的速度处理请求。
最后更新于