首页 我们 服务 网站建设 移动应用 案例 资讯 联系
业务专线:15989169178

期待聆听您的声音

15989169178

不忽悠,不作恶,不欺诈;敬天理,存良知,思利他。
QQ咨询 QQ咨询 QQ咨询
服务网点:广州 深圳 佛山 粤西

与我们一起分享美好

常见的服务限流算法

发布时间:2023-02-23 发布作者:睿思设计 查阅次数:1863次 标签:

在开发高并发系统的时候,我们一般通过三种方式去保障系统服务稳定:服务降级、服务限流和缓存。对于缓存在实际开发中使用的比较多,这个是大家的共识没有什么异议的。今天我们的主角是服务限流,在此之前我们先来看下服务限流 和 服务降级 的区别:


服务降级


服务降级是在服务器压力陡增的情况下,利用现有的资源,关闭一些服务接口或者页面,以此来释放服务器资源保证核心任务的正常运行。


服务限流


限流本质上是减少流量的访问,而服务的处理能力不变;而对于服务降级来说是降低了部分服务的处理能力,增加另一部分服务处理能力,访问量不变。


本篇文章中说到的服务限流不是 nginx 层面的限流,而是业务代码中的逻辑限流。


那么,我们为什么要服务限流?


从服务调用方来说,可以把服务简单的划分为以下几种类型的服务


1.与用户打交道的服务


比如 web 服务,对外 API,这种类型的服务有以下几种可能会导致服务器压力变大:

用户增长过快

热点事件

恶意的攻击/刷单

爬虫
这些情况都是无法预知的,我们不知道什么时候请求流量会突增,如果真的要是碰到这种情况,扩容根本是来不及的


2.对内的 RPC 服务


一个服务 A 的接口可能会被其他 BCDE 多个服务调用,如果其中一个服务的流量突增比如 B 服务,导致 A 服务压力变大甚至挂掉,那么这个时候也不能给 CDE 服务提供服务。
这种情况在实际开发中时常发生。


常见的限流算法


下面我们来看几种实际业务场景中常用的几种限流算法:计数器算法、漏桶算法、令牌桶算法。


计数器算法


计数器算法应该是最简单,最容易想到的限流策略。限流的本质是限制某一个 API 在某个维度单位时间内处理请求的次数。我们可以设置一个计数器对某一时间段内的请求进行计数,当请求量超过事先设定好的阈值,拒绝用户的请求。比如限流的 QPS 是100,算法的实现思路是从第一个请求进来开始计数,在接下来的 1s 内,每来一个请求计数器自动加 1,如果累加的数字超过 100,那么后续的请求就会被拒绝,等到 1s 结束后,计数器开始重置为 0,重新开始计数。


这种方式存在弊端


弊端1:如果在 1s 的前 10ms 请求数已经达到了 100,那么剩下的 990ms,服务调用方就要眼巴巴的看着请求被拒绝。


弊端2:如果有一个恶意的用户在 999ms 的时候瞬间发送了 100 次请求,并且又在 1000ms 时瞬间发送了 100 次请求,那么其实这个用户在 1s 内发送了 200 次请求。利用时间窗口的重置节点处突发请求,可以瞬间超过我们服务本身能承受的压力,瞬间压垮服务。


针对计数器算法的漏洞一个比较经典的处理方案是采用 滑动窗口。比如我们把上面的 1min 内 100 次请求上限看成是一个大的时间窗口,然后把这个窗口进一步细分,比如每 10 s 一个小窗口,该窗口的频率上限同样设置成 100,这样大窗口包含 16 个小窗口,并且每过 10s 大窗口就移动一个小窗口长度。如果一个恶意用户在 09:59:30~09:59:59 之间发送了 100 次请求,等到了10:00:00~10:00:30 时 100 次计数仍然是有效的,所以,这个时间段新的请求仍然会被拒绝。


漏桶算法


漏桶算法是限流方面比较经典的算法。可以把该算法联想成一个具体的漏桶模型,漏桶始终以一个恒定的速率往外排水,如果桶被装满的话则后来涌入的水会溢出。对应到接口限流来说,用户的请求可以看做是水,不管用户的请求量有多大多不均衡,能够被处理的请求速率是恒定的,而且能够接受的请求数也是有上限的,超出上限的请求会被拒绝,在算法实现方面可以准备一个队列来作为漏桶的实现,用这个队列保存请求,通过一个线程池定期从队列中获取请求并执行,也可以一次性获取多个并发请求,如下图:

漏桶算法也存在一个弊端:无法应对短时间的突发流量


令牌桶算法


在令牌桶算法中,存在一个桶,用来存放固定数量的令牌。算法中存在一种机制,以一定的速率往桶中放令牌。每次请求调用需要先获取令牌,只有拿到令牌才有机会继续执行,否则请求选择等待或者服务直接拒绝请求。


放令牌这个动作是持续不断的进行,如果桶中令牌数量达到上限,就丢弃令牌,所以,会存在这样的一种情况,桶中一直有大量的令牌,这时进来的请求就可以直接拿到令牌执行。比如我们把 QPS 设置成 100,那么限流器完成初始化 1s 后,桶中已经有 100 个令牌,这时候服务还未完全启动好,等启动完成功对外提供服务时,该限流器可以抵挡瞬时的 100 个请求。所以,当桶中没有令牌时请求才会等待或者被拒绝,当没有请求申请令牌时,那么这个令牌桶会溢出。在这里令牌桶类似一个 buffer,请求密度比较低或者处于冷却状态下,令牌桶会溢出,当请求流量突增时,则过去积累的结余资源直接可以拿来借用,从这里可以看出这点弥补了漏桶算法的不足。

实现思路:可以准备一个队列,用于存放令牌,另外通过一个线程池定期生成令牌存放到队列中,没来一个请求就从队列中取出一个令牌,并继续执行。


上面我们提到的限流算法主要是针对于单机限流,实际业务场景更加的复杂,业务的需求五花八门,简单的单机限流很难满足需求。


比如为了限制某个资源被某个用户访问的次数,10 s 只能访问 3 次,或者一天只能访问 100 次,这种需求通过单机限流是无法实现的,这时就需要通过集群限流的方式实现。


如何实现?为了实现对访问次数的限制,肯定需要一个计数器,那么我们需要把这个计数器放在哪里呢?因为这个限流是在集群层面实现的,集群形式存在的情况才需要分布式限流,由于 redis 天生对分布式支持非常友好,所以 redis 成了一个很好的选择。


大致思路:每次有相关的操作时候,我们就向 redis 服务器发送一个 incr 命令。比如限制某个用户访问接口的次数,当用户请求过来时我们使用用户 ID 和 接口名称生成对应 key,每次该用户访问这个接口时,只需要对这个 key 增加 1,并且给这个 key 设置有效期,这样就可以简单的实现指定时间内的访问效率。


对于排名不稳定的老网站优化应该怎么做?

这是最后一条了哦

我们的位置

广州 广州市黄埔区科学城科学大道18号芯大厦 159 8916 9178

深圳 深圳市南山区大冲国际中心九楼 159 1543 2684

粤西 茂名市茂南区油城三路粤西创业创新孵化基地B110 157 6767 8148

我们的服务

网站及移动应用 高端品牌网站 APP开发 小程序开发 微信运营

系统应用开发 OA/ERP/CRM/HR系统开发 教学管理系统 电商系统 应用型软件系统定制开发

了解我们

公司简介 联系我们 我们的案例 新闻资讯

使用条款 隐私声明 Cookies

© 2009-2024 广州睿网信息科技有限公司 版权所有 粤ICP备16051058号