RateLimiter限流锁

基础使用

// 初始化一个限流器
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种实例对象,SmoothBurstySmoothWarmingUp

根据不同的初始化参数会生成不同的实例,使用上的区别主要在于限流的模式和效果,即平滑突发限流和平滑预热限流。

  • 平滑突发限流(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

参考资料

  1. Guava RateLimiter – Throttling Explained
  2. Guava源码:com.google.common.util.concurrent.SmoothRateLimiter
  3. A Guide to Guava’s RateLimiter
posted @ 2023-03-13 20:54  LYRiver  阅读(140)  评论(0编辑  收藏  举报