限流是什么?怎么限流?
1.为什么需要限流?
限流(Rate Limiting)是一种控制数据或服务访问速率的技术,通常用于防止滥用、保护系统免受过载和攻击,以及确保服务质量。通过限制访问速率,限流可以确保系统的稳定性和可靠性,并防止单个用户或来源过度消耗资源。
限流的基本原理是在一定时间段内限制对特定资源或服务的请求速率。这可以通过设置阈值来实现,例如每秒允许的最大请求数。当请求速率超过阈值时,系统可以采取不同的策略来处理额外的请求,例如拒绝请求、延迟处理或限制请求的频率。
下面是一个简单的例子来帮助你理解限流的概念:
就像去⾃助餐厅吃饭,如果有⼈⼀股脑地把所有美⻝都拿光了,其他⼈就⽆法享用。所以,我们需要对此做出一些限制,以便其他用户正常享用。
2.限流算法
固定窗口限流
固定窗口限流算法是一种最简单的限流算法,其原理是在固定时间窗口(单位时间)内限制请求的数量。该算法将时间分成固定的窗口,并在每个窗口内限制请求的数量。具体来说,算法将请求按照时间顺序放入时间窗口中,并计算该时间窗口内的请求数量,如果请求数量超出了限制,则拒绝该请求。假设单位时间是1秒,限流阀值为3。在单位时间1秒内,每来一个请求,计数器就加1,如果计数器累加的次数超过限流阀值3,后续的请求全部拒绝。等到1秒结束后,计数器清0,重新开始计数。
编辑
缺点:可出现流量突刺
限定:1 ⼩时只允许 10 个⽤户操作
⽐如:前 59 分钟没有 1 个操作,第 59 分钟来了 10 个操作;第 1 ⼩时 01 分钟⼜来 了 10 个操作。相当于 2 分钟内执⾏了 20 个操作,服务器仍然有⾼峰危险。
滑动窗口限流算法
滑动窗口限流算法是一种更为复杂的限流算法,它解决了固定窗口限流算法存在的问题。在滑动窗口限流算法中,时间窗口不再是固定的,而是根据请求的到达时间动态滑动。算法将时间划分为多个小窗口,每个窗口有一定的计数器,用于记录该窗口内的请求数量。当请求到达时,根据请求的时间戳确定其所属的窗口,并将计数器加1。如果某个窗口内的请求数量超过了设定的阈值,则后续的请求将被拒绝或限制。
优点:能够解决上述流量突刺的问题,因为第 59 分钟时,限流窗口是 59 分 ~1 小时 59 分,这个时间段内只能接受 10 次请求,只要还在这个窗⼝内,更多的操作就会被拒绝。
缺点:实现相对固定窗⼝来说⽐较复杂,限流效果和你的滑动单位有关,过大的时间窗口可能导致无法及时处理突发流量,而过小的时间窗口可能导致频繁地滑动窗口和重置计数器,增加系统的开销。因此,在实际应用中需要进行充分的测试和调优来确定合适的时间窗口大小和滑动步长。
漏桶算法
特点:以固定的速率处理请求(漏水),当请求桶满了后,拒绝请求。
举例:每秒处理 10 个请求,桶的容量是 10,每 0.1 秒固定处理⼀次请求,如果 1 秒 内来了 10 个请求,这 10 此请求都可以处理完。
但如果 1 秒内来了 11 个请求,最后那个请求就会溢出桶,被拒绝请求。
优点:能够⼀定程度上应对流量突刺,能够固定速率处理请求,保证服务器的安全。
缺点:没有固定速率处理⼀批请求,只能⼀个⼀个按顺序来处理(固定速率的缺点)
令牌桶限流
令牌桶算法(Token Bucket Algorithm) 令牌桶算法可以看作⼀个令牌桶,其中令牌以恒定的速率产⽣。当⼀个请求到达时,如果令牌桶中仍然有令牌,则该请求得到处理并从令牌桶中减去⼀个令牌。如果令牌桶中没有令牌,则请求将被拒绝。 在此算法中,令牌代表请求能够被处理的数量,⽽桶则代表着请求被处理的容器。
举例:
管理员先⽣成⼀批令牌,每秒⽣成 10 个令牌;当⽤户要操作前,先去拿到⼀个令牌,有令牌的⼈就有资格执⾏操作、同时执⾏操作;拿不到令牌的就等着。
优点:能够并发处理同时的请求,并发性能会更高
令牌桶算法可以缓解漏桶算法的缺点,但在⼀些场景下可能存在⼀定问题。⽐如在 应对短时间内的⾼并发请求时,由于令牌数有限,引⼊过⼤的并发请求会导致严重 的性能问题,也可能会造成请求失败或者拒绝。
3.限流粒度
限流粒度是指在进行流量限制时所采用的控制粒度
针对某个方法限流:这种限流粒度是指对特定的方法进行流量限制,即单位时间内最多允许同时执行X个操作使用这个方法。这可以用于保护某个关键方法不被过度调用,以防止系统过载或资源耗尽。例如,一个系统中可能存在一个查询数据库的方法,为了保护数据库不被大量并发请求压垮,可以对这个方法进行限流,确保每个时刻最多只有X个操作在使用该方法。针对某个用户限流:这种限流粒度是针对单个用户的操作进行流量限制,即单个用户在单位时间内最多执行X次操作。这可以用于防止某些用户过度使用系统资源或滥用API接口。例如,在一个Web应用程序中,某个用户可能频繁发送请求,导致服务器负载过高,通过针对该用户进行限流,可以限制其请求的频率,保护系统的稳定性。针对某个用户X方法限流:这种限流粒度结合了前两种粒度,针对单个用户在单位时间内对特定方法的调用进行限制。例如,单个用户在单位时间内最多执行X次某个方法。这可以用于在保护关键方法的同时,也防止某些用户对该方法的滥用。这种限流粒度更加精细,可以根据具体情况对特定用户和方法进行细粒度的控制。
通过合理设置限流粒度,可以更好地保护系统的稳定性和性能,防止由于流量过大而导致的系统崩溃或性能下降。同时,也可以防止某些用户或恶意行为对系统造成不必要的负担或损害。
4.限流实现
1.本地限流(单机限流)
每个服务器单独限流,⼀般适⽤于单体项⽬,就是你的项⽬只有⼀个服务器。 在 Java 中,有很多第三⽅库可以⽤来实现单机限流: Guava RateLimiter:这是⾕歌 Guava 库提供的限流⼯具,可以对单位时间内的请求 数量进⾏限制。
2.分布式限流 (集群限流)
分布式限流(集群限流)适用于以下场景:
高并发系统:在开发高并发系统时,为了保护系统并提升性能,常常需要采用限流措施。分布式限流可以在多个应用服务器之间进行协调,限制整个集群的请求流量,从而保护系统免受过载和崩溃的风险。稀缺资源场景:对于稀缺资源的场景,如秒杀、抢购等,需要限制并发请求量,以避免资源被过度消耗或滥用。分布式限流可以在整个集群范围内对这些请求进行限制,确保系统的稳定性和公平性。写服务场景:对于写服务场景,如评论、下单等,需要限制请求的速率,以减轻数据库和服务器的压力。分布式限流可以根据集群的负载情况和容量限制,对写服务进行限速,防止系统过载。频繁复杂查询场景:对于频繁复杂查询的场景,如评论的最后几页等,需要限制查询的请求量,避免对数据库产生过大的负载。分布式限流可以限制这类查询的请求速率,保护数据库的稳定性和性能。
总之,分布式限流适用于需要在多个应用服务器之间进行协调限流的场景,可以保护系统免受过载和崩溃的风险,并确保资源的合理使用和公平性。在选择是否使用分布式限流时,需要综合考虑系统的需求、特点以及集群的规模等因素。
3.Redisson 限流实现
Redisson 内置了⼀个限流工具类,可以帮助你利⽤ Redis 来存储、来统计。
①Redis安装包
链接:https://pan.baidu.com/s/1JFVJ4rLo3yYQAHdClYuuAg?pwd=togj
编辑
启动成功:
②引⼊ Redisson 依赖
③application.yml
④创建 RedissonConfig 配置类,⽤于初始化 RedissonClient 对象单例:
⑤测试
因为限流器设置为 1秒能接受2个请求。但是测试中 1秒发送了3个请求,故此在第三次请求的时候,会抛出异常。