Guava RateLimiter限流

令牌桶算法

  • 令牌桶是按照固定速率往桶中添加令牌,请求是否被处理需要看桶中令牌是否足够,当令牌数减为零时则拒绝新的请求;漏桶则是按照常量固定速率流出请求,流入请求速率任意,当流入的请求数累积到漏桶容量时,则新流入的请求被拒绝;
  • 令牌桶限制的是平均流入速率,允许突发请求,只要有令牌就可以处理,支持一次拿3个令牌,4个令牌;漏桶限制的是常量流出速率,即流出速率是一个固定常量值,比如都是1的速率流出,而不能一次是1,下次又是2,从而平滑突发流入速率;
  • 令牌桶允许一定程度的突发,而漏桶主要目的是平滑流出速率;

Guava RateLimiter

Guava的 RateLimiter提供了令牌桶算法实现:平滑突发限流(SmoothBursty)和平滑预热限流(SmoothWarmingUp)实现。

平滑突发限流

使用 RateLimiter的静态方法创建一个限流器,设置每秒放置的令牌数为5个。
返回的RateLimiter对象可以保证1秒内不会给超过5个令牌,并且以固定速率进行放置,达到平滑输出的效果。

public void testSmoothBursty() {RateLimiter r = RateLimiter.create(5);while (true) {System.out.println("get 1 tokens: " + r.acquire() + "s");}/*** output: 基本上都是0.2s执行一次,符合一秒发放5个令牌的设定。* get 1 tokens: 0.0s* get 1 tokens: 0.182014s* get 1 tokens: 0.188464s* get 1 tokens: 0.198072s* get 1 tokens: 0.196048s* get 1 tokens: 0.197538s* get 1 tokens: 0.196049s*/
}

令牌累计

Guava RateLimiter的令牌积累数量是根据设定的速率和时间间隔来计算的。具体计算方式如下:

  1. 首先,RateLimiter会根据设定的速率(每秒生成的令牌数量)计算出令牌生成的时间间隔。
    例如,如果设定的速率是2个令牌/秒,那么每个令牌生成的时间间隔是0.5秒(1秒/2个令牌)。
  2. 当RateLimiter开始工作时,它会记录当前时间,并将令牌桶中的令牌数量初始化为0。
  3. 当一个请求到达时,RateLimiter会计算当前时间与上一次记录时间之间的时间间隔,并根据设定的速率和时间间隔计算出应该生成的令牌数量。
  4. 如果计算出的令牌数量小于等于令牌桶中的剩余令牌数量,请求将被允许通过,并且令牌桶中的令牌数量减少。
  5. 如果计算出的令牌数量大于令牌桶中的剩余令牌数量,请求将被限制或延迟处理,直到令牌桶中有足够的令牌可用。
    总结来说,Guava RateLimiter根据设定的速率和时间间隔来计算应该生成的令牌数量,并根据令牌桶中的剩余令牌数量来决定请求是否被允许通过。
public void testSmoothBursty2() {// RateLimiter使用令牌桶算法,会进行令牌的累积,如果获取令牌的频率比较低,则不会导致等待,直接获取令牌。RateLimiter r = RateLimiter.create(2);while (true) {try {Thread.sleep(3000);} catch (Exception e) {}System.out.println("get 1 tokens: " + r.acquire(1) + "s");System.out.println("get 1 tokens: " + r.acquire(1) + "s");System.out.println("get 1 tokens: " + r.acquire(1) + "s");System.out.println("get 1 tokens: " + r.acquire(1) + "s");System.out.println("end");/*** output:get 1 tokens: 0.0sget 1 tokens: 0.0sget 1 tokens: 0.0sget 1 tokens: 0.499147sendget 1 tokens: 0.0sget 1 tokens: 0.0sget 1 tokens: 0.0sget 1 tokens: 0.499904s*/}
}

在上面的代码中,令牌桶中最多只能积累2个令牌是由于创建RateLimiter时指定的速率为2。RateLimiter.create(2)表示每秒生成2个令牌。令牌桶的大小取决于速率和时间间隔之间的关系。在这种情况下,速率为2个令牌/秒,意味着每秒生成2个令牌放入令牌桶中。

根据令牌桶算法,令牌桶的大小可以理解为令牌桶的容量,即最多可以容纳的令牌数量。在这里,令牌桶的容量为2,也就是最多可以积累2个令牌。

如果在某个时间点上,令牌桶中已经有2个令牌,而没有请求来消耗这些令牌,那么令牌桶中不会继续积累更多的令牌。新的令牌只有在之前的令牌被消耗后才会生成并放入令牌桶中。

因此,根据上述代码和速率设置,令牌桶中最多只能积累2个令牌。

平滑预热限流

RateLimiter的 SmoothWarmingUp是带有预热期的平滑限流,它启动后会有一段预热期,逐步将分发频率提升到配置的速率。 比如下面代码中的例子,创建一个平均分发令牌速率为2,预热期为3分钟。由于设置了预热时间是3秒,令牌桶一开始并不会0.5秒发一个令牌,而是形成一个平滑线性下降的坡度,频率越来越高,在3秒钟之内达到原本设置的频率,以后就以固定的频率输出。这种功能适合系统刚启动需要一点时间来“热身”的场景。

public void testSmoothwarmingUp() {RateLimiter r = RateLimiter.create(2, 3, TimeUnit.SECONDS);while (true){System.out.println("get 1 tokens: " + r.acquire(1) + "s");System.out.println("get 1 tokens: " + r.acquire(1) + "s");System.out.println("get 1 tokens: " + r.acquire(1) + "s");System.out.println("get 1 tokens: " + r.acquire(1) + "s");System.out.println("end");/*** output:* get 1 tokens: 0.0s* get 1 tokens: 1.329289s* get 1 tokens: 0.994375s* get 1 tokens: 0.662888s  上边三次获取的时间相加正好为3秒* end* get 1 tokens: 0.49764s  正常速率0.5秒一个令牌* get 1 tokens: 0.497828s* get 1 tokens: 0.49449s* get 1 tokens: 0.497522s*/}
}

在平滑预热限流的情况下,令牌是不会积累的。
RateLimiter.create(2, 3, TimeUnit.SECONDS);

  • 参数1:每秒产生2个令牌
  • 参数2/3:在前3秒内,产生3个令牌,且从慢到快
  • 如果RateLimiter.create(2, 4, TimeUnit.SECONDS); 代表在前4秒内,产生4个令牌,且从慢到快

核心函数说明

函数说明示例
public static RateLimiter create(double permitsPerSecond)每秒产生permitsPerSecond个令牌RateLimiter.create(2)
public static RateLimiter create(double permitsPerSecond, long warmupPeriod, TimeUnit unit)每秒产生permitsPerSecond个令牌,在前warmupPeriod单位时间内,产生warmupPeriod个令牌,从慢到快RateLimiter.create(2, 3, TimeUnit.SECONDS)
public double acquire(int permits)取得指定数量的令牌,并返回等待时间limiter.acquire(1)
public boolean tryAcquire(int permits)尝试取得指定数量的令牌,返回成功或失败limiter.tryAcquire(1)
public boolean tryAcquire(Duration timeout)尝试取得1个令牌,并等待指定的时间,返回成功或失败limiter.tryAcquire(Duration.ofSeconds(1))
public boolean tryAcquire(int permits, long timeout, TimeUnit unit)尝试取得指定数量的令牌,并等待指定的时间,返回成功或失败limiter.tryAcquire(2, 10, TimeUnit.SECONDS)

参考

  • https://zhuanlan.zhihu.com/p/60979444

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/61620.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ctfshow 红包题

前言&#xff1a; 最近一直在搞java很少刷题&#xff0c;看见ctfshow的活动赶紧来复现一波~ ctfshow 红包挑战7 <?php highlight_file(__FILE__); error_reporting(2); extract($_GET); ini_set($name,$value); system("ls ".filter($_GET[1])."" )…

集合框架-(Collection/Map)

1.单列集合 1.1基础概要 集合中存储的是对象的地址信息&#xff0c;想要输出对象的信息&#xff0c;需要在具体的类中重写toString&#xff08;&#xff09;方法 Collection代表单列集合&#xff0c;每个元素数据只包含一个值 List集合&#xff1a;添加的元素可以是有序、可…

_kbhit() and getch() 在小游戏中用不了。因为控制台函数,仅在控制台程序中可用

太长不看版&#xff1a; _kbhit() and getch() 包含在conio.h中。 conio是Console Input/Output&#xff08;控制台输入输出&#xff09;的简写&#xff0c;其中定义了通过控制台进行数据输入和数据输出的函数&#xff0c;主要是一些用户通过按键盘产生的对应操作&#xff0c…

ZooKeeper技术内幕

文章目录 1、系统模型1.1、数据模型1.2、节点特性1.2.1、节点类型 1.3、版本——保证分布式数据原子性操作1.4、 Watcher——数据变更的通知1.5、ACL——保障数据的安全1.5.1、权限模式&#xff1a;Scheme1.5.2、授权对象&#xff1a;ID1.5.3、权限扩展体系 2、序列化与协议2.1…

【狂神】Spring5笔记(1-9)

目录 首页&#xff1a; 1.Spring 1.1 简介 1.2 优点 2.IOC理论推导 3.IOC本质 4.HelloSpring ERROR 5.IOC创建对象方式 5.1、无参构造 这个是默认的 5.2、有参构造 6.Spring配置说明 6.1、别名 6.2、Bean的配置 6.3、import 7.DL依赖注入环境 7.1 构造器注入 …

Pydantic 学习随笔

这里是零散的记录一些学习过程中随机的理解&#xff0c;因此这里的记录不成体系。如果是想学习 Pydantic 建议看官方文档&#xff0c;写的很详细并且成体系。如果有问题需要交流&#xff0c;欢迎私信或者评论。 siwa 报 500 Pydantic 可以和 siwa 结合使用&#xff0c;这样既…

hyperf 十五 验证器

官方文档&#xff1a;Hyperf 验证器报错需要配合多语言使用&#xff0c;创建配置自动生成对应的语言文件。 一 安装 composer require hyperf/validation:v2.2.33 composer require hyperf/translation:v2.2.33php bin/hyperf.php vendor:publish hyperf/translation php bi…

React和Redux中的不变性

https://overreacted.io/zh-hans/a-complete-guide-to-useeffect/ 一、不变性和副作用 1.不变&#xff1a;不断创造新值来替换旧值 2.不变性规则&#xff1a; &#xff08;1&#xff09;当给定相同的输入时&#xff0c;纯函数必须始终返回相同的值 &#xff08;2&#xff0…

如何利用Python代码优雅的进行文件下载

如何利用Python代码优雅的进行文件下载 一、什么是wget&#xff1f;二、使用wget.exe客户端进行文件下载三、使用Python脚本进行文件下载 欢迎学习交流&#xff01; 邮箱&#xff1a; z…1…6.com 网站&#xff1a; https://zephyrhours.github.io/ 一、什么是wget&#xff1f;…

JavaWeb_LeadNews_Day9-Redis实现用户行为

JavaWeb_LeadNews_Day9-Redis实现用户行为 网关配置点赞阅读不喜欢关注收藏文章详情-行为数据回显来源Gitee 网关配置 nacos: leadnews-app-gateway # 用户行为微服务 - id: leadnews-behavioruri: lb://leadnews-behaviorpredicates:- Path/behavior/**filters:- StripPrefi…

yolov3

yolov1 传统的算法 最主要的是先猜很多候选框&#xff0c;然后使用特征工程来提取特征&#xff08;特征向量&#xff09;,最后使用传统的机器学习工具进行训练。然而复杂的过程可能会导致引入大量的噪声&#xff0c;丢失很多信息。 从传统的可以总结出目标检测可以分为两个阶…

Java 读取TIFF JPEG GIF PNG PDF

Java 读取TIFF JPEG GIF PNG PDF 本文解决方法基于开源 tesseract 下载适合自己系统版本的tesseract &#xff0c;官网链接&#xff1a;https://digi.bib.uni-mannheim.de/tesseract/ 2. 下载之后安装&#xff0c;安装的时候选择选择语言包&#xff0c;我选择了中文和英文 3.…

提高Python并发性能 - asyncio/aiohttp介绍

在进行大规模数据采集时&#xff0c;如何提高Python爬虫的并发性能是一个关键问题。本文将向您介绍使用asyncio和aiohttp库实现异步网络请求的方法&#xff0c;并通过具体结果和结论展示它们对于优化爬虫效率所带来的效果。 1. 什么是异步编程&#xff1f; 异步编程是一种非阻…

vue使用打印组件print-js

项目场景&#xff1a; 由于甲方要求&#xff0c;项目需要打印二维码标签&#xff0c;故开发此功能 开发流程 安装包&#xff1a;npm install print-js --saveprint-js的使用 <template><div id"print" ref"print" ><p>打印内容<p&…

树的介绍(C语言版)

前言 在数据结构中树是一种很重要的数据结构&#xff0c;很多其他的数据结构和算法都是通过树衍生出来的&#xff0c;比如&#xff1a;堆&#xff0c;AVL树&#xff0c;红黑色等本质上都是一棵树&#xff0c;他们只是树的一种特殊结构&#xff0c;还有其他比如linux系统的文件系…

CocosCreator3.8研究笔记(二)windows环境 VS Code 编辑器的配置

一、设置文件显示和搜索过滤步骤 为了提高搜索效率以及文件列表中隐藏不需要显示的文件&#xff0c; VS Code 需要设置排除目录用于过滤。 比如 cocoscreator 中&#xff0c;编辑器运行时会自动生成一些目录&#xff1a;build、temp、library&#xff0c; 所以应该在搜索中排除…

代码随想录算法训练营第五十一天 | 309.最佳买卖股票时机含冷冻期,714.买卖股票的最佳时机含手续费

代码随想录算法训练营第五十一天 | 309.最佳买卖股票时机含冷冻期&#xff0c;714.买卖股票的最佳时机含手续费 309.最佳买卖股票时机含冷冻期714.买卖股票的最佳时机含手续费 309.最佳买卖股票时机含冷冻期 题目链接 视频讲解 给定一个整数数组prices&#xff0c;其中第 pric…

Mysql-索引查询相关

一、单表查询 1.1 二级索引为null 不论是普通的二级索引&#xff0c;还是唯一二级索引&#xff0c;它们的索引列对包含 NULL 值的数量并不限制&#xff0c;所以我们采用key IS NULL 这种形式的搜索条件最多只能使用 ref 的访问方法&#xff0c;而不是 const 的访问方法 1.2 c…

深入探索PHP编程:连接数据库的完整指南

深入探索PHP编程&#xff1a;连接数据库的完整指南 在现代Web开发中&#xff0c;与数据库进行交互是不可或缺的一部分。PHP作为一种强大的服务器端编程语言&#xff0c;提供了丰富的工具来连接和操作各种数据库系统。本篇教程将带您了解如何在PHP中连接数据库&#xff0c;执行…

并发编程的故事——并发之共享模型

并发之共享模型 文章目录 并发之共享模型一、多线程带来的共享问题二、解决方案三、方法中的synchronize四、变量的线程安全分析五、习题六、Monitor七、synchronize优化八、wait和notify九、sleep和wait十、park和unpark十一、重新理解线程状态十二、多把锁十三、ReentrantLoc…