基础使用
// 初始化一个限流器
RateLimiter rateLimiter = RateLimiter.create(2);
// 执行限流方法
void doSomething(){
rateLimiter.acquire();
// do something
}
使用 com.google.common.util.concurrent.RateLimiter#create(double)
创建一个限流器,参数为每秒允许的执行次数。
使用 com.google.common.util.concurrent.RateLimiter#acquire()
执行限流方法,获取不到令牌时底层会通过sleep等待。
1)RateLimiter 基于令牌桶算法,即以用户设定的恒定速率向令牌桶内放置令牌,用户来执行任务时,只有拿到令牌才能执行。
2)RateLimiter 对于持续生成令牌,采用的不是定时任务的方式(过于耗费资源,不适合高并发),而是使用延迟计算的方式,即在获取令牌时计算上一次时间 nextFreeTicketMicros 和当前时间之间的差值,计算这段时间之内按照用户设定的速率可以生产多少令牌。
3)RateLimiter 是一个抽象类,它有两个子类 SmoothBursty 和 SmoothWarmingUp。SmoothBursty 允许突发流量的平滑限流器,它使用了令牌桶算法。SmoothWarmingUp 是平滑预热限流器,它使用了漏桶算法。
效果测试
RateLimiter一主要有2种实例对象,SmoothBursty
和 SmoothWarmingUp
根据不同的初始化参数会生成不同的实例,使用上的区别主要在于限流的模式和效果,即平滑突发限流和平滑预热限流。
- 平滑突发限流(SmoothBursty)是指在没有请求时,会累积一些许可证,当有突发的请求时,可以快速响应,但是随后的请求会被平均分配到固定的时间间隔中。这种模式适用于对响应时间敏感的场景。
- 平滑预热限流(SmoothWarmingUp)是指在开始时,许可证的发放速度较慢,然后逐渐提升到稳定状态。这种模式适用于需要避免冷启动问题的场景。
创建和使用方法如下:
// 创建一个每秒生成2个令牌的限流器
RateLimiter rateLimiter = RateLimiter.create(2);
// 创建一个预热时间为10毫秒,每秒生成5个令牌的限流器
RateLimiter rateLimiter = RateLimiter.create(5, 10, TimeUnit.MILLISECONDS);
// 请求服务时,调用 acquire 方法获取令牌,并返回等待时间
double waitTime = rateLimiter.acquire();
System.out.println("Wait time: " + waitTime + " seconds");
// 或者调用 tryAcquire 方法尝试获取令牌,并返回是否成功
boolean success = rateLimiter.tryAcquire();
System.out.println("Success: " + success);
其中RateLimiter的默认实现即是已经存储1个令牌的限流器
可以用以下代码测试:
@Test
public void testRateLimiter() throws InterruptedException {
RateLimiter rateLimiter = RateLimiter.create(2);
// 情况一:连续请求10次
for (int i = 0; i < 5; i++) {
// 获取许可证并打印等待时间
double waitTime = rateLimiter.acquire();
System.out.println("Wait time: " + waitTime);
}
RateLimiter smoothWarmingUp = RateLimiter.create(2, 3, TimeUnit.SECONDS);
for (int i = 0; i < 10; i++) {
// 获取许可证并打印等待时间
double waitTime = smoothWarmingUp.acquire();
System.out.println("SmoothWarmingUp Wait time: " + waitTime);
}
}
Wait time: 0.0
Wait time: 0.497882
Wait time: 0.4902
Wait time: 0.494686
Wait time: 0.494838
SmoothWarmingUp Wait time: 0.0
SmoothWarmingUp Wait time: 1.33317
SmoothWarmingUp Wait time: 0.996481
SmoothWarmingUp Wait time: 0.665705
SmoothWarmingUp Wait time: 0.496102
SmoothWarmingUp Wait time: 0.495545
SmoothWarmingUp Wait time: 0.498759
SmoothWarmingUp Wait time: 0.498779
SmoothWarmingUp Wait time: 0.495724
SmoothWarmingUp Wait time: 0.495912
参考资料
- Guava RateLimiter – Throttling Explained
- Guava源码:com.google.common.util.concurrent.SmoothRateLimiter
- A Guide to Guava’s RateLimiter