【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过滤器进行一个简单的 ...
随机推荐
- concurrent.futures性能阐述
python因为其全局解释器锁GIL而无法通过线程实现真正的平行计算.这个论断我们不展开,但是有个概念我们要说明,IO密集型 vs. 计算密集型. IO密集型:读取文件,读取网络套接字频繁. 计算密集 ...
- Madlibs
name1 = input('请输入一个名字:') name2 = input('再输入一个名字:') animal = input('请输入一种动物:') print('一二三四五{}上山打{}不在 ...
- license
http://139.199.89.239:1008/4571ab86-eb0d-4d2b-999e-37406bb8ba38 _~~~ rO0ABXNyAChjb20uemVyb3R1cm5hcm9 ...
- 直播流RTMP 知识
分享直播相关知识点: http://blog.csdn.net/kingroc/article/details/50839994 #!/bin/bash# Order Finish Startup# ...
- Linux下好用的屏幕录像软件kazam及截图软件shutter
都是apt直接安装即可使用. 其中kazam默认保存的文件格式是avi,非常大,通常录制几十秒就已经好几个G,导致录制过程太占用资源,会出现卡顿的现象. 在“首选项”中可以选择输出格式为mp4,文件就 ...
- 《Serverless架构-无服务单页应用开发》读后感
本书的作者是[美]Ben Rady,译者郑赞美.简传挺,书中作者详细的介绍了如何使用html.js以及amazon提供的诸多云服务(Simple Storage Service(S3).Cognito ...
- pom.xml文件模板、application文件模板、configuration逆向生成文件、
pom: <?xml version="1.0" encoding="UTF-8"?><project xmlns="http:// ...
- Python3.* 和Python2.*的区别
许多Python初学者都会问:我应该学习哪个版本的Python.对于这个问题,我的回答通常是“先选择一个最适合你的Python教程,教程中使用哪个版本的Python,你就用那个版本.等学得差不多了,再 ...
- 协程 及 libco 介绍
libco 是腾讯开源的一个协程库,主要应用于微信后台RPC框架,下面我们从为什么使用协程.如何实现协程.libco使用等方面了解协程和libco. why协程 为什么使用协程,我们先从server框 ...
- Java基础巩固——排序
快速排序 基本思想: 通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分关键字小,则分别对两部分继续进行排序,直到整个序列有序. 实例: 1.一趟排序的过程: 2.排序的全 ...