限流-RateLimit简单工具使用

举报
object 发表于 2024/03/15 17:16:25 2024/03/15
【摘要】 之前分享了常见的几种限流算法,今天分享一种开箱即用的单体服务的限流工具,RateLimit,他是guava工具包下的一个工具类,提供了简单的令牌桶实现。文章后附带主要的函数说明引入依赖<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>31.0.1-...

之前分享了常见的几种限流算法,今天分享一种开箱即用的单体服务的限流工具,RateLimit,他是guava工具包下的一个工具类,提供了简单的令牌桶实现。文章后附带主要的函数说明

引入依赖

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.0.1-jre</version>
</dependency>

代码实现如下。 

可以看到代码比较简单, 创造了一个5个每秒速率生成令牌的桶, 而桶的容量也为5个,几乎获取每个令牌的获取速度 1个/0.2s。


public static void main(String[] args) {
    RateLimiter rateLimiter = RateLimiter.create(5); // 使用RateLimter类创造令牌桶,入参为产生令牌速率,单位为 个/秒。
    for (int i = 0; i < 20; i++) {
        double acquire = rateLimiter.acquire();  // 获取令牌,返回等待获取令牌的时间
        System.out.println("成功获取token,等待时间为:" + acquire + "秒");
    }
}
// 输出
/*
成功获取token,等待时间为:0.0秒
成功获取token,等待时间为:0.198399秒
成功获取token,等待时间为:0.198066秒
成功获取token,等待时间为:0.19955秒
成功获取token,等待时间为:0.186172秒
成功获取token,等待时间为:0.19967秒
成功获取token,等待时间为:0.185074秒
成功获取token,等待时间为:0.199708秒
成功获取token,等待时间为:0.196223秒
成功获取token,等待时间为:0.199479秒
成功获取token,等待时间为:0.199672秒
成功获取token,等待时间为:0.190289秒
成功获取token,等待时间为:0.188873秒
成功获取token,等待时间为:0.199786秒
成功获取token,等待时间为:0.1995秒
成功获取token,等待时间为:0.195466秒
成功获取token,等待时间为:0.199815秒
成功获取token,等待时间为:0.189331秒
成功获取token,等待时间为:0.199878秒
成功获取token,等待时间为:0.186387秒
*/

acquire这个函数不会拒绝线程,只会阻塞线程,要达到拒绝线程,可以使用tryAcquire函数 ,代码示例如下:

public static void main(String[] args) {
    RateLimiter rateLimiter = RateLimiter.create(5);
    for (int i = 0; i <10; i++) {
        boolean result = rateLimiter.tryAcquire();
        try {
            Thread.sleep(100); // 自旋太快,添加等待时间,补充令牌
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (result) { 
            System.out.println("成功获取令牌!"); // 获取成功,模拟处理业务
        } else {
            System.out.println("已经没有令牌了,请稍后再访问"); // 获取失败,模拟拒绝业务
        }
    }
}
// 输出
/*
成功获取令牌!
已经没有令牌了,请稍后再访问
成功获取令牌!
已经没有令牌了,请稍后再访问
成功获取令牌!
已经没有令牌了,请稍后再访问
成功获取令牌!
已经没有令牌了,请稍后再访问
成功获取令牌!
已经没有令牌了,请稍后再访问
*/

RateLimit还有一个预热的功能,通过设置需要预热的时间,达到启动时低速率产生令牌,运行平稳后,高速度运行。只需创建时,添加预热时间

代码示例如下

可以看到,位置前,产品速度是0.2s几乎稳定, 设置后, 前3秒依次增快,直到达到0.2s每个的稳定温度

public static void main(String[] args) {
    RateLimiter rateLimiter = RateLimiter.create(5, 3, TimeUnit.SECONDS); // 指定预热时间 3  单位秒
    for (int i = 0; i <10; i++) {
        double acquire = rateLimiter.acquire();
        System.out.println("成功获取token,等待时间为:" + acquire + "秒");
    }
}
// 输出
/*
成功获取token,等待时间为:0.0秒
成功获取token,等待时间为:0.571911秒
成功获取token,等待时间为:0.48963秒
成功获取token,等待时间为:0.457989秒
成功获取token,等待时间为:0.413039秒
成功获取token,等待时间为:0.359573秒
成功获取token,等待时间为:0.291227秒
成功获取token,等待时间为:0.253623秒
成功获取token,等待时间为:0.205956秒
成功获取token,等待时间为:0.199385秒
*/

甚至还有动态调整令牌生成速度函数  setRate。 可以根据状态进行动态调整。就不代码展示了,附相关的函数介绍

修饰符和类型 方法和描述
double acquire() 从RateLimiter获取一个许可,该方法会被阻塞直到获取到请求
double acquire(int permits)从RateLimiter获取指定许可数,该方法会被阻塞直到获取到请求
static RateLimiter create(double permitsPerSecond)根据指定的稳定吞吐率创建RateLimiter,这里的吞吐率是指每秒多少许可数(通常是指QPS,每秒多少查询)
static RateLimiter create(double permitsPerSecond, long warmupPeriod, TimeUnit unit)根据指定的稳定吞吐率和预热期来创建RateLimiter,这里的吞吐率是指每秒多少许可数(通常是指QPS,每秒多少个请求量),在这段预热时间内,RateLimiter每秒分配的许可数会平稳地增长直到预热期结束时达到其最大速率。(只要存在足够请求数来使其饱和)
double getRate()返回RateLimiter 配置中的稳定速率,该速率单位是每秒多少许可数
void setRate(double permitsPerSecond)更新RateLimite的稳定速率,参数permitsPerSecond 由构造RateLimiter的工厂方法提供。
String toString()返回对象的字符表现形式
boolean tryAcquire()从RateLimiter 获取许可,如果该许可可以在无延迟下的情况下立即获取得到的话
boolean tryAcquire(int permits)从RateLimiter 获取许可数,如果该许可数可以在无延迟下的情况下立即获取得到的话
boolean tryAcquire(int permits, long timeout, TimeUnit unit)从RateLimiter 获取指定许可数如果该许可数可以在不超过timeout的时间内获取得到的话,或者如果无法在timeout 过期之前获取得到许可数的话,那么立即返回false (无需等待)
boolean tryAcquire(long timeout, TimeUnit unit)从RateLimiter 获取许可如果该许可可以在不超过timeout的时间内获取得到的话,或者如果无法在timeout 过期之前获取得到许可的话,那么立即返回false(无需等待)
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。