【Guava】使用Guava的RateLimiter做限流
一、常见的限流算法
目前常用的限流算法有两个:漏桶算法和令牌桶算法。
1.漏桶算法
漏桶算法的原理比较简单,请求进入到漏桶中,漏桶以一定的速率漏水。当请求过多时,水直接溢出。可以看出,漏桶算法可以强制限制数据的传输速度。
2.令牌桶算法
令牌桶算法的原理是系统以一定速率向桶中放入令牌,如果有请求时,请求会从桶中取出令牌,如果能取到令牌,则可以继续完成请求,否则等待或者拒绝服务。这种算法可以应对突发程度的请求,因此比漏桶算法好。
在 Wikipedia 上,令牌桶算法是这么描述的:
- 每秒会有 r 个令牌放入桶中,或者说,每过 1/r 秒桶中增加一个令牌
- 桶中最多存放 b 个令牌,如果桶满了,新放入的令牌会被丢弃
- 当一个 n 字节的数据包到达时,消耗 n 个令牌,然后发送该数据包
- 如果桶中可用令牌小于 n,则该数据包将被缓存或丢弃
二、RateLimiter
Guava中开源出来一个令牌桶算法的工具类RateLimiter,可以轻松实现限流的工作。RateLimiter 对简单的令牌桶算法做了一些工程上的优化,具体的实现是 SmoothBursty。需要注意的是,RateLimiter 的另一个实现 SmoothWarmingUp,就不是令牌桶了,而是漏桶算法。也许是出于简单起见,RateLimiter 中的时间窗口能且仅能为 1s,如果想搞其他时间单位的限流,只能另外造轮子。
RateLimiter 有一个有趣的特性是「前人挖坑后人跳」,也就是说 RateLimiter 允许某次请求拿走超出剩余令牌数的令牌,但是下一次请求将为此付出代价,一直等到令牌亏空补上,并且桶中有足够本次请求使用的令牌为止。这里面就涉及到一个权衡,是让前一次请求干等到令牌够用才走掉呢,还是让它先走掉后面的请求等一等呢?Guava 的设计者选择的是后者,先把眼前的活干了,后面的事后面再说。
测试代码:
public class RateLimiterMain {
public static void main(String[] args) {
RateLimiter rateLimiter = RateLimiter.create(2);
System.out.println(rateLimiter.acquire(5));
System.out.println(rateLimiter.acquire(2));
System.out.println(rateLimiter.acquire(1));
}
}
输出内容:
0.0
2.496889
0.992149
可以看出,令牌桶每秒只能产生2个令牌,我们可以第一次取出5个,但是第二个再去取令牌的时候,需要等2.5s,也就是第一次令牌取完后,需要等2.5s才能取到令牌。同样的,第三次取1个令牌的时候,也需要等待第二次的1s的时间。也就是,取的速率可以超过令牌产生的速率,但是下一次再次去取的时候,需要阻塞等待。
当然也可以使用tryAcquire来非阻塞的获取,可以实时返回结果。另外tryAcquire也可以传入参数,也就是等待的时间,超时直接返回false。这点等同于常见的lock,tryLock。
三、并发控制Semaphore
一般来说,在网关系统中,还有一个参数叫并发控制,就是某一个资源可以被同时访问的个数。这种情况下,我们可以使用Semaphore来控制。
Semaphore不同于互斥锁。互斥锁是某个资源只能支持同时一个访问,而Semaphore可以支持多个访问,但是加上了总数的控制。
感兴趣的同学可以继续深入了解Semaphore的使用。
【Guava】使用Guava的RateLimiter做限流的更多相关文章
- 超详细的Guava RateLimiter限流原理解析
超详细的Guava RateLimiter限流原理解析 mp.weixin.qq.com 点击上方“方志朋”,选择“置顶或者星标” 你的关注意义重大! 限流是保护高并发系统的三把利器之一,另外两个是 ...
- guava的限流工具RateLimiter使用
guava限流工具使用 非常详细的一篇使用博客:https://www.cnblogs.com/yeyinfu/p/7316972.html 1,原理:Guava RateLimiter基于令牌桶算法 ...
- Google Guava缓存实现接口的限流
一.项目背景 最近项目中需要进行接口保护,防止高并发的情况把系统搞崩,因此需要对一个查询接口进行限流,主要的目的就是限制单位时间内请求此查询的次数,例如1000次,来保护接口. 参考了 开涛的博客聊聊 ...
- 使用RateLimiter完成简单的大流量限流,抢购秒杀限流
RateLimiter是guava提供的基于令牌桶算法的实现类,可以非常简单的完成限流特技,并且根据系统的实际情况来调整生成token的速率. 通常可应用于抢购限流防止冲垮系统:限制某接口.服务单位时 ...
- SpringBoot进阶教程(六十七)RateLimiter限流
在上一篇文章nginx限流配置中,我们介绍了如何使用nginx限流,这篇文章介绍另外一种限流方式---RateLimiter. v限流背景 在早期的计算机领域,限流技术(time limiting)被 ...
- 分布式限流组件-基于Redis的注解支持的Ratelimiter
原文:https://juejin.im/entry/5bd491c85188255ac2629bef?utm_source=coffeephp.com 在分布式领域,我们难免会遇到并发量突增,对后端 ...
- 集群、限流、缓存 BAT 大厂无非也就是这么做
前言 前阵子有网友询问,如何优化网站?这个问题真的很大,跟他简单的聊了一下,随便说了几点,觉得有必要整理一篇文章出来,正好前阵子在做爬虫博客,于是把大体思路分享出来,与大家互通有无,共同进步. 优化 ...
- Redis除了做缓存--Redis做消息队列/Redis做分布式锁/Redis做接口限流
1.用Redis实现消息队列 用命令lpush入队,rpop出队 Long size = jedis.lpush("QueueName", message);//返回存放的数据条数 ...
- SpringCloud(8)---zuul权限校验、接口限流
zuul权限校验.接口限流 一.权限校验搭建 正常项目开发时,权限校验可以考虑JWT和springSecurity结合进行权限校验,这个后期会总结,这里做个基于ZuulFilter过滤器进行一个简单的 ...
随机推荐
- es6数组
将两类对象转为真正的数组 Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括ES6新增的数据结构Set和 ...
- dubbo入门学习 六 admin管理界面
1. 本质就是一个web项目 2. 获取注册中心内Provider注册的信息.用页面呈现出来. 3. 实现步骤 3.1 把dubbo-admin-2.5.3.war上传到服务器tomcat中. 3.2 ...
- CODEFORCES ROUND #761 ANALYSES BY TEAM:RED & BLACK
A. Dasha and Stairs Problems: 一个按照1,2,3……编号的楼梯,给定踩过的编号为奇数奇数和偶数的楼梯数量a和b,问是否可以有区间[l, r]符合奇数编号有a个,偶数编号有 ...
- s6-3 通信模型
传输层的作用范围 通信5元组 一些已分配的知名端口 三元组 协议. 本地端点. 远方端点 五元组 协议. 本地IP地址.本地端口号. 远端IP地址.远端端口号 通信5元组 源IP 源端口 目的I ...
- input checkbox复选框取值
<table> <!--列表表头 开始 --> <tr class="ui-widget ui-state-hover" style="he ...
- 探寻TP-Link路由器的登录验证
提示:该案例仅供学习使用,切勿滥用!!! 查找路由器连接地址 查找ip $ ifconfig enp2s0: flags=<UP,BROADCAST,RUNNING,MULTICAST> ...
- virtualenv搭建
1.准备工作 终端 网络状况良好 2.安装虚拟环境 如何安装虚拟环境: 2.1了解你的电脑中有哪些版本的python whereis python 查看当前系统中有多少跟python有关的命令 ...
- 关于整数溢出和NaN的问题
当Integer i = Integer.MAX_VALUE;i + 1 < i成立, Double.NaN与任何数(包括自己)比较都为false,与js的NaN一样 如下: //整数溢出 In ...
- kubernetes CRD学习笔记
前言 最近在极客时间订阅了kubernetes的专栏,这篇文章是想记录一下自己学习CRD(custom resource definition)的过程,加深一下记忆. 准备工作 首先安装一下我们用的g ...
- 《python语言程序设计》_第4章_选择
第四章 # 4.1 引言 布尔表达式:选择语句选择的条件. 程序: import math #加载math模块radius=eval(input("Enter an integer:&quo ...