在高并发访问下,比如电商大促活动,流量持续不断的涌入,服务之间的相互调用频率突然增加,引发系统负载过高,这时系统所依赖的服务的稳定性对系统的影响非常大,而且还有很多不确定因素引起雪崩,如网络连接中断,服务宕机等。一般微服务容错组件提供了限流、隔离、降级、熔断等手段,可以有效保护我们的微服务系统。本文主要说说限流。
限流,就是限制最大流量,防止操作频率超过定义的限制。系统能提供的最大并发有限,同时请求又太多,这就就需要限流,比如秒杀、大促活动业务,瞬时大量请求涌入,服务器服务不过来,就只好限流了。速率限制通过限制在给定时间段内可以到达 API 的请求数量来保护服务免受意外或恶意过度使用。在没有速率限制的情况下,任何用户都可以用请求轰炸您的服务器,从而导致其他用户饿死的情况。
接下来,我们将介绍四种常见的限流算法
漏桶算法的思路,是一种简单直观的算法,就是⼀个固定容量的漏桶,按照常量固定速率流出⽔滴。如果桶是空的,则不需流出水滴。可以以任意速率流入水滴到漏桶。如果流入水滴超出了桶的容量,则流入的水滴溢出了(被丢弃),而漏桶容量是不变的。
这种算法的优点是它可以平滑请求的突发并以恒定的速率处理它们。它也很容易在负载均衡器上实现,并且对每个用户来说都是高效的内存。无论请求的数量如何,都保持到服务器的恒定接近均匀的流量。
缺点是请求的爆发可能会填满存储桶,导致新请求的匮乏。它也不能保证请求在给定的时间内完成。
优点:
缺点:
令牌桶算法:假设限制2r/s,则按照500毫秒的固定速率往桶中添加令牌。桶中最多存放b个令牌,当桶满时,新添加的令牌被丢弃或拒绝。当一个n个字节大小的数据包到达,将从桶中删除n个令牌,接着数据包被发送到网络上。如果桶中的令牌不足n个,则不会删除令牌,且该数据包将被限流(要么丢弃,要么缓冲区等待)。令牌桶限流原理,如图所示。
限流服务器端的令牌桶可以根据实际服务性能和时间段来调整生成令牌的速度和桶的容量。当需要提高速率时,可以按需增加放入桶中的令牌速率
生成令牌的速度是恒定的,而请求获取令牌的速度没有限制。这意味着当面对瞬时大流量时,该算法可以在短时间内获取大量令牌,而且获取令牌的过程并不会消耗很多资源
当每次新的请求到达服务器时,会执行两个操作:
该算法具有内存效率,因为我们为我们的应用程序为每个用户节省了更少的数据量。这里的问题是它可能导致分布式环境中的竞争条件。当来自两个不同应用程序服务器的两个请求同时尝试获取令牌时,就会发生这种情况。
优点:
缺点:
在固定的时间窗口内,允许一定数量的请求进入。超过数量则拒绝或排队等待下一个时间段。这种计数器限流的实现方式是在时间间隔内进行限制。如果用户在上一个时间间隔结束前发送请求(但未超过限制),同时在当前时间间隔开始时也发送请求(同样未超过限制),那么在各自的时间间隔内,这些请求都是正常的。然而,当请求在时间间隔的临界时间段内超过系统限制时,可能会导致系统过载
由于计数器算法存在时间临界点缺陷,因此在时间临界点左右的极短时间段内容易遭到攻击。比如设定每分钟最多可以请求100次某个接口,如12:00:00-12:00:59时间段内没有数据请求,而12:00:59-12:01:00时间段内突然并发100次请求,而紧接着跨入下一个计数周期,计数器清零,在12:01:00-12:01:01内又有100次请求。那么也就是说在时间临界点左右可能同时有2倍的阀值进行请求,从而造成后台处理请求过载的情况,导致系统运营能力不足,甚至导致系统崩溃。
缺点:
例如:限流是每秒3个,在第一秒的最后一毫秒发送了3个请求,在第二秒的第一毫秒又发送了3个请求。在这两毫米内处理了6个请求,但是并没有触发限流。如果出现突发流量,可能会压垮服务器。
滑动窗⼝算法是把固定时间间进行划分,并且随着时间移动,移动方式为开始时间点变为时间列表中的第二时间点,结束时间点增加一个时间点,不断重复,通过这种方式可以巧妙的避开计数器的临界点的问题。
滑动窗口算法可以有效的规避计数器算法中时间临界点的问题,但是仍然存在时间片段的概念。同时滑动窗口算法计数运算也相对固定时间窗口算法比较耗时。
缺点: 还是存在限流不够平滑的问题。例如:限流是每秒3个,在第一毫秒发送了3个请求,达到限流,剩余窗口时间的请求都将会被拒绝,体验不好。
介绍了四种常用的限流算法:固定窗口算法、滑动窗口算法、漏桶算法和令牌桶算法。每种算法都有其特点和适用场景,下面我们来对它们进行简单的总结和比较。
以上是四种常用限流算法掌握一身,面试必过的详细内容。更多信息请关注PHP中文网其他相关文章!