限流-RateLimit简单工具使用
【摘要】 之前分享了常见的几种限流算法,今天分享一种开箱即用的单体服务的限流工具,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)