Guava RateLimiter限流

这篇具有很好参考价值的文章主要介绍了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.0s
         get 1 tokens: 0.0s
         get 1 tokens: 0.0s
         get 1 tokens: 0.499147s
         end
         get 1 tokens: 0.0s
         get 1 tokens: 0.0s
         get 1 tokens: 0.0s
         get 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);文章来源地址https://www.toymoban.com/news/detail-691923.html

  • 参数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

到了这里,关于Guava RateLimiter限流的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Guava-RateLimiter详解

    简介:  常用的限流算法有漏桶算法和令牌桶算法,guava的RateLimiter使用的是令牌桶算法,也就是以固定的频率向桶中放入令牌,例如一秒钟10枚令牌,实际业务在每次响应请求之前都从桶中获取令牌,只有取到令牌的请求才会被成功响应,获取的方式有两种:阻塞等待令牌或

    2024年02月06日
    浏览(37)
  • Java的guava 限流写法

    就这么简单!

    2024年02月11日
    浏览(29)
  • SpringBoot利用Guava实现单机app限流访问

    物料准备: 1.引入Guava依赖 2.定义一个限流注解作用于api接口的方法上 3.定义一个切面,对注解标注的方法实现一个限流访问 使用方法,把@RateLimitAspect 注解添加到需要限流的API接口上即可,如 添加到@GetMapping 或 @PostMapping上

    2024年02月11日
    浏览(35)
  • 【Guava笔记01】Guava Cache本地缓存的常用操作方法

    这篇文章,主要介绍Guava Cache本地缓存的常用操作方法。 目录 一、Guava Cache本地缓存 1.1、引入guava依赖 1.2、CacheBuilder类 1.3、Guava-Cache使用案例

    2024年01月23日
    浏览(40)
  • com.google.guava:guava 组件安全漏洞及健康分析

    维护者 google组织 许可证类型 Apache-2.0 首次发布 2010 年 4 月 26 日 最新发布时间 2023 年 8 月 1 日 GitHub Star 48189 GitHub Fork 10716 依赖包 28,694 依赖存储库 219,576 Guava 是 Google 的一组核心 Java 库,其中包括新的集合类型(例如 multimap 和 multiset)、不可变集合、图形库以及用于并发、

    2024年02月10日
    浏览(47)
  • 【Guava】Guava: Google Core Libraries for Java 好用工具类

    Guava是Google的一组核心Java库,其中包括 新的集合类型 (如multimap和multiset) 、 不可变集合 、 图库 ,以及用于 并发、I/O、哈希、缓存、基元、字符串 等的实用程序!它 被广泛用于谷歌内的大多数Java项目,并被许多人广泛使用。 Guava是一种基于开源的Java库 ,Google Guava源于

    2024年02月11日
    浏览(39)
  • Guava Cache 介绍

    Guava 是 Google 提供的一套 Java 工具包,而 Guava Cache 是该工具包中提供的一套完善的 JVM 级别高并发缓存框架;本文主要介绍它的相关功能及基本使用,文中所使用到的软件版本:Java 1.8.0_341、Guava 32.1.3-jre。 缓存在很多情况下非常有用。例如,当某个值的计算或检索代价很高,

    2024年02月05日
    浏览(42)
  • 再见,Guava!再见,Ehcache!

    缓存(Cache)在代码世界中无处不在。从底层的CPU多级缓存,到客户端的页面缓存,处处都存在着缓存的身影。缓存从本质上来说,是一种空间换时间的手段,通过对数据进行一定的空间安排,使得下次进行数据访问时起到加速的效果。 就Java而言,其常用的缓存解决方案有很多

    2024年02月13日
    浏览(34)
  • Guava:Ordering 排序工具

    排序器  Ordering  是 Guava流畅风格比较器  Comparator  的实现,它可以用来为构建复杂的比较器,以完成集合排序的功能。 从实现上说,Ordering 实例就是一个特殊的 Comparator 实例。Ordering 把很多基于 Comparator 的静态方法(如  Collections.max )包装为自己的实例方法(非静态方法

    2024年02月01日
    浏览(36)
  • 限流器 github的ratelimiter

    2024年02月22日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包