接口限流算法:漏桶算法令牌桶算法
工作中对外提供的API 接口设计都要考虑限流,如果不考虑限流,会成系统的连锁反应,轻者响应缓慢,重者系统宕机,整个业务线崩溃,如何应对这种情况呢,我们可以对请求进行引流或者直接拒绝等操作,保持系统的可用性和稳定性,防止因流量暴增而导致的系统运行缓慢或宕机。
在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流
缓存:缓存的目的是提升系统访问速度和增大系统处理容量
降级:降级是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行
限流:限流的目的是通过对并发访问/请求进行限速,或者对一个时间窗口内的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务、排队或等待、降级等处理
限流算法
常用的限流算法有令牌桶和和漏桶,而Google开源项目Guava中的RateLimiter使用的就是令牌桶控制算法。
漏桶算法
把请求比作是水,水来了都先放进桶里,并以限定的速度出水,当水来得过猛而出水不够快时就会导致水直接溢出,即拒绝服务。
漏斗有一个进水口 和 一个出水口,出水口以一定速率出水,并且有一个最大出水速率:
在漏斗中没有水的时候,
- 如果进水速率小于等于最大出水速率,那么,出水速率等于进水速率,此时,不会积水
- 如果进水速率大于最大出水速率,那么,漏斗以最大速率出水,此时,多余的水会积在漏斗中
在漏斗中有水的时候
- 出水口以最大速率出水
- 如果漏斗未满,且有进水的话,那么这些水会积在漏斗中
- 如果漏斗已满,且有进水的话,那么这些水会溢出到漏斗之外
令牌桶算法
对于很多应用场景来说,除了要求能够限制数据的平均传输速率外,还要求允许某种程度的突发传输。这时候漏桶算法可能就不合适了,令牌桶算法更为适合。
令牌桶算法的原理是系统以恒定的速率产生令牌,然后把令牌放到令牌桶中,令牌桶有一个容量,当令牌桶满了的时候,再向其中放令牌,那么多余的令牌会被丢弃;当想要处理一个请求的时候,需要从令牌桶中取出一个令牌,如果此时令牌桶中没有令牌,那么则拒绝该请求。
RateLimiter 用法
https://github.com/google/guava
添加依赖
<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>26.0-jre</version><!-- or, for Android: --><version>26.0-android</version>
</dependency>
public class Test {public static void main(String[] args) {ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(100));// 指定每秒放1个令牌RateLimiter limiter = RateLimiter.create(1);for (int i = 1; i < 50; i++) {// 请求RateLimiter, 超过permits会被阻塞//acquire(int permits)函数主要用于获取permits个令牌,并计算需要等待多长时间,进而挂起等待,并将该值返回Double acquire = null;if (i == 1) {acquire = limiter.acquire(1);} else if (i == 2) {acquire = limiter.acquire(10);} else if (i == 3) {acquire = limiter.acquire(2);} else if (i == 4) {acquire = limiter.acquire(20);} else {acquire = limiter.acquire(2);}executorService.submit(new Task("获取令牌成功,获取耗:" + acquire + " 第 " + i + " 个任务执行"));}}
}
class Task implements Runnable {String str;public Task(String str) {this.str = str;}@Overridepublic void run() {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");System.out.println(sdf.format(new Date()) + " | " + Thread.currentThread().getName() + str);}
}
响应
2018-08-11 00:26:22.953 | pool-1-thread-1获取令牌成功,获取耗:0.0 第 1 个任务执行
2018-08-11 00:26:23.923 | pool-1-thread-2获取令牌成功,获取耗:0.98925 第 2 个任务执行
2018-08-11 00:26:33.920 | pool-1-thread-3获取令牌成功,获取耗:9.996993 第 3 个任务执行
2018-08-11 00:26:35.920 | pool-1-thread-4获取令牌成功,获取耗:1.999051 第 4 个任务执行
2018-08-11 00:26:55.920 | pool-1-thread-5获取令牌成功,获取耗:19.999726 第 5 个任务执行
2018-08-11 00:26:57.920 | pool-1-thread-6获取令牌成功,获取耗:1.999139 第 6 个任务执行
2018-08-11 00:26:59.920 | pool-1-thread-7获取令牌成功,获取耗:1.999806 第 7 个任务执行
2018-08-11 00:27:01.919 | pool-1-thread-8获取令牌成功,获取耗:1.999433 第 8 个任务执行
acquire
函数主要用于获取permits个令牌,并计算需要等待多长时间,进而挂起等待,并将该值返回
一个RateLimiter主要定义了发放permits的速率。如果没有额外的配置,permits将以固定的速度分配,单位是每秒多少permits。默认情况下,Permits将会被稳定的平缓的发放。
预消费能力
从输出结果可以看出,指定每秒放1个令牌,RateLimiter具有预消费的能力:
acquire 1
时,并没有任何等待 0.0 秒 直接预消费了1个令牌
acquire 10
时,由于之前预消费了 1 个令牌,故而等待了1秒,之后又预消费了10个令牌
acquire 2
时,由于之前预消费了 10 个令牌,故而等待了10秒,之后又预消费了2个令牌
acquire 20
时,由于之前预消费了 2 个令牌,故而等待了2秒,之后又预消费了20个令牌
acquire 2
时,由于之前预消费了 20 个令牌,故而等待了20秒,之后又预消费了2个令牌
acquire 2
时,由于之前预消费了 2 个令牌,故而等待了2秒,之后又预消费了2个令牌
acquire 2
时 …
通俗的讲「前人_挖坑_后人跳」,也就说上一次请求获取的permit数越多,那么下一次再获取授权时更待的时候会更长,反之,如果上一次获取的少,那么时间向后推移的就少,下一次获得许可的时间更短。可见,都是有代价的。正所谓:要浪漫就要付出代价。马上就七夕了,浪漫的代价可能要花钱啊,单身狗们。
令牌桶算法VS漏桶算法
漏桶
漏桶的出水速度是恒定的,那么意味着如果瞬时大流量的话,将有大部分请求被丢弃掉(也就是所谓的溢出)。
令牌桶
生成令牌的速度是恒定的,而请求去拿令牌是没有速度限制的。这意味,面对瞬时大流量,该算法可以在短时间内请求拿到大量令牌,而且拿令牌的过程并不是消耗很大的事情。
最后
不论是对于令牌桶拿不到令牌被拒绝,还是漏桶的水满了溢出,都是为了保证大部分流量的正常使用,而牺牲掉了少部分流量,这是合理的,如果因为极少部分流量需要保证的话,那么就可能导致系统达到极限而挂掉,得不偿失。
本文讲的单机的限流,是JVM级别的的限流,所有的令牌生成都是在内存中,在分布式环境下不能直接这么用,可用使redis限流。
接口限流算法:漏桶算法令牌桶算法相关推荐
- 信号量与令牌桶_限流的4种方式令牌桶实战
限流的4种方式 正文 限流 限流是对某一时间窗口内的请求数进行限制,保持系统的可用性和稳定性,防止因流量暴增而导致的系统运行缓慢或宕机.常用的限流算法有令牌桶和和漏桶,而Google开源项目Guava ...
- 什么是限流?为什么会限流呢?常见的限流算法【固定窗口限流、滑动窗口限流、漏桶限流、令牌桶限流】是什么呢?
什么是限流?为什么会限流呢?常见的限流算法[固定窗口限流.滑动窗口限流.漏桶限流.令牌桶限流]是什么呢? 什么是限流? 为什么会限流? 1. 固定窗口限流算法 1.1 什么是固定窗口限流算法 1.2 ...
- 接口限流算法:漏桶算法amp;令牌桶算法
转载自 接口限流算法:漏桶算法&令牌桶算法 背景 每一个对外提供的API接口都是需要做流量控制的,不然会导致系统直接崩溃.很简单的例子,和保险丝的原理一样,如果用电符合超载就会烧断保险丝断掉电 ...
- 高并发策略之限流:计数器、漏桶、令牌桶 三大算法的原理与实战(史上最全)
导读 网站高可用指的就是:在绝大多的时间里,网站一直处于可以对外提供服务的正常状态. 一般以"年"为单位来统计,"9"的个数越多,代表一年中允许的不可用时间就越 ...
- 令牌桶算法和漏桶算法python_限流之漏桶算法与令牌桶算法
在开发高并发系统时有三把利器用来保护系统:缓存.降级和限流 缓存:缓存的目的是提升系统访问速度和增大系统处理容量 降级:降级是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降 ...
- 带你快速了解:限流中的漏桶和令牌桶算法
在前文 <限流熔断是什么,怎么做,不做行不行?>中针对 "限流" 动作,有提到流量控制其内部对应着两种常用的限流算法. 其分别对应漏桶算法和令牌桶算法.因此会有的读者会 ...
- 使用令牌桶算法解决调用第三方接口限流问题
我们在调用第三方接口时常常会碰到接口限流问题,为了解决这一问题,大家想出了许多方法.我这里介绍一下我的方法,第三方接口限流一般是基于令牌桶算法的,那么我们可以以彼之道还治彼身,使用令牌桶算法实现我方调 ...
- 用令牌桶算法完成API接口限流
这是张富涛的第15篇原创 用令牌桶算法完成API接口限流 本文介绍了"令牌桶算法",和使用lua+redis实现基于令牌桶算法的限流. 1. 限流需求的产生背景 软件开发时偶尔会面 ...
- 【面试大全-高并发】-限流策略有哪些,滑动窗口算法和令牌桶区别,使用场景
参考思路:限流算法常用的几种实现方式有如下四种:计数器.滑动窗口.漏桶和令牌桶: ● 计数器: ○ 思想:在固定时间窗口内对请求进行计数,与阀值进行比较判断是否需要限流,一旦到了时间临界点,将计数器清 ...
最新文章
- AndroidStudio3.0无法打开Android Device Monitor的解决办法(An error has occurred on Android Device Monitor)...
- 15、Cocos2dx 3.0游戏开发找小三之Sprite:每一个精灵都是上辈子折翼的天使
- 【随机共振】基于随机共振的高频弱信号检测的MATLAB仿真
- dom4j Java解析xml应用
- MTK 驱动开发(43)---GPS问题分类--MTK ALPS GPS的特殊知识
- [渝粤教育] 西南科技大学 高速铁路线路与车站 在线考试复习资料
- 简单的汉字和十六进制转换
- 安装oracle创建的数据库实例,oracle创建数据库实例
- 高质量C/C++编程指南
- java下载文件excel格式错乱,excel表格数据错乱如何修复-excel表格里的文件突然格式全部乱了,怎么恢复?...
- android 电视安装apk文件损坏,安装电视软件时提示解析包出现问题怎么破?
- 「解析」netron 模型可视化
- 鱼塘钓鱼(fishing)
- android实现自动触摸,Android编程开发之多点触摸(Multitouch)实现方法
- vue中接口返回数据过大回显导致页面崩溃解决方法
- mpeg格式转换成mp4,mpeg转mp4
- 适合前端新手的十大网站
- 采集人物经历来佐证子平术
- 用python画小猪佩奇的编码有注释_啥是佩奇?使用Python自动绘画小猪佩奇的代码实例...
- MSDTC Service的访问权限
热门文章
- RunTime的使用-Category改变整个项目全部字体
- 翻译:微软style的并行计算
- Scala的基本语法总结
- Silverlight 3发布新版3.0.50106.0
- 三星android获取root权限,三星G9250(S6 Edge公开版全网通 Android 5.1)获取ROOT权限详解教程...
- 区块链技术开发三个优势
- valve 的设计_向Valve Portal开发人员学习游戏设计原则
- 数据通信技术(三:VLAN划分)
- Python多进程与进程锁的基本使用
- php字符串转换表达式,php处理字符串格式的计算表达式