常见的几种限流算法
降级,熔断,限流的区别:
先导篇:服务降级、熔断、限流的区别
以设计一个整点限量秒杀系统为例,包括登录、抢购、支付等核心功能
- 降级(丢车保帅):在秒杀时,通过服务降级把注册、修改个人信息等非核心功能关闭掉。
- 熔断:支付依赖第三方服务,要设置熔断策略,熔断后要给出友好提示,比如10分钟后再来支付。
- 限流:抢购下单接口采用限流方式,如抢购1000件商品,则设置2000大小的队列,请求超过2000后直接拒绝掉。
几种常用的限流算法
限流又称为流量控制,是指限制到达系统的并发请求数,当达到限制条件则可以拒绝请求,可以起到保护下游服务,防止服务过载等作用。
此处的流,可以视为是一个抽象的概念;可以是CDN或音视频传输的字节流流量,可以是接口请求的QPS,可以是业务流频度,甚至可以是数据读写频度。
而限流算法就是对服务 按照预设的规则,进行流量限制或功能限制的一种方法。
字节QA的这篇常用的限流算法,一大半内容和上文雷同..
https://xie.infoq.cn/article/bf4eeabeecf0d87b399c82e4e
http://dockone.io/article/9746
https://juejin.cn/post/7002027704912445448
Go生态比较流行的基于漏桶限流算法实现的限流库uber-go/ratelimit
Go生态比较流行的基于令牌桶限流算法实现的限流库 juju/ratelimit,Go官方也提供了相关功能,在golang.org/x/time/rate
计数器算法(即 固定窗口算法)
分成多个时间片段,每个时间片段分配一定数量的请求额度。
每个时间片段相对隔离,一个时间片段区间的请求量统计跟其他区间的请求量统计完全独立。当一个时间片段过期,自动进入下一个时间片段重新进行计数,逻辑图如下:
弊端:
算法相对简单,但会存在临界问题
临界问题 :用户流量并不会像我们所期望的那样匀速请求,而可能在某个时间点集中爆发。
如上图所示:每个时间片段为1s。 在第一个时间单位内的前800ms只有一次请求,后200ms(800ms-1s范围内)内承载999次请求,而第二个时间单位内前200ms承载1001-2000次共1000个请求。这样系统在400ms(第800ms到1200ms时间范围内)内共承载了1999次用户请求,此访问量已经达到系统所能承载的最大QPS 1000次请求的两倍。
滑动窗口算法
滑动窗口算法的时间单位不再是彼此独立,而是步步递进,彼此重叠。
滑动窗口算法将固定窗口算法的时间单位 进一步细化,如将1秒再分为10个时间网格,每个网格占用100ms的时间。第一个时间单位为0ms-1000ms、第二个时间单位为100ms-1100ms、第三个时间单位为200ms-1200ms,以此类推。每个时间单位的请求总量都需小于设定的最大请求量。
弊端:
由于滑动窗口算法每次都需要统计单位时间的请求量,开销远大于固定窗口算法,所以在真实的业务环境中需要慎重使用滑动窗口算法。
漏桶算法
漏桶算法以绝对平均的速度处理用户请求,无论用户请求有多少,最终消费/处理 用户请求的速率是固定不变的。
1 | package main |
运行,然后使用ab来进行压测:
ab -n 10 -c 2 http://127.0.0.1:8080/ping
其中-n表示请求数,-c表示并发数
上一个请求处理的时间是at
每秒请求量(RPS)
弊端
在真实的业务场景中,漏桶算法面对合法的突发流量,有点捉襟见肘。
令牌桶算法
这两种方法(漏桶和令牌桶)看起来很像,不过还是有区别的。漏桶流出的速率固定,而令牌桶只要在桶中有令牌,那就可以拿。也就是说令牌桶是允许一定程度的并发的,比如同一个时刻,有100个用户请求,只要令牌桶中有100个令牌,那么这100个请求全都会放过去。令牌桶在桶中没有令牌的情况下也会退化为漏桶模型,实际应用中令牌桶应用较为广泛。
对比
来自 常用限流算法
来自 图解+代码|常见限流算法以及限流在单机分布式场景下的思考
来自 一文搞懂高频面试题之限流算法,从算法原理到实现,再到对比分析
nginx的限流策略以及google的guava限流策略。
市面上一些比较成熟的限流工具和框架:
Google的Guava中基于令牌桶实现的限流组件,拿来即用;Guava 是一个 Google 开源项目,包含了若干被 Google 的 Java 项目广泛依赖的核心库,其中的 RateLimiter 提供了令牌桶算法实现:平滑突发限流 (SmoothBursty) 和平滑预热限流 (SmoothWarmingUp) 实现。
Alibaba开源的面向分布式服务架构的流量控制框架Sentinel,基于滑动窗口实现
Nginx: 对于 Nginx 接入层限流可以使用 Nginx 自带了两个模块:1. 连接数限流模块
ngx_http_limit_conn_module
; 2. 漏桶算法实现的请求限流模块ngx_http_limit_req_module
原文作者: fliter
原文链接:
http://www.dashen.tech/2022/05/02/常见的几种限流算法/版权声明: 转载请注明出处