学习使用Guava RateLimiter

目录

一、引入

  在程序中,我们经常会用到限流,比如接口调用的频率限制。

  server端提供api给clients进行调用,如果某个client调用api的频率过高,造成server端的负载升高,超过server端的上限,那么很有可能导致server端不可用,从而影响所有的调用方。

  限制频率,可以在client端做,也可以在server端做,但是目前一般都是在server端做,同时client一般也会调整调用频率。

  至于怎么限流,网上很多的资料,这里就不阐述了,主要介绍一下使用Guava RateLimiter来实现限流。

二、快速上手

2.1、导入依赖

  Guava RateLimiter是Guava的一部分,所以直接导入Guava的依赖即可。

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

  

2.2、第一个示例

  简单看一下下面的用法

扫描二维码关注公众号,回复: 9037406 查看本文章
package cn.ganlixin.guava;

import com.google.common.util.concurrent.RateLimiter;
import org.junit.Test;

import java.time.LocalTime;

public class UserRateLimiter {

    @Test
    public void testSimple() throws InterruptedException {
        // 创建一个限流器(每秒限制流量为5个)
        RateLimiter rateLimiter = RateLimiter.create(5.0);

        for (int i = 0; i < 10; i++) {
            if (rateLimiter.tryAcquire()) {
                System.out.println(LocalTime.now() + " 通过");
            } else {
                System.out.println(LocalTime.now() + " 被限流");
            }
            Thread.sleep(100L);
        }
    }
}

  上面的示例代码中,创建了一个限流器,每秒最多允许5个流量,这个流量有个专业的称呼,叫“许可”(准许调用),也就是5个许可。

  调用tryAcquire()会尝试获取1个许可,如果获取到了,返回true,表示未被限流;否则返回false,表示没有获取到许可,被限流了。

  如此就可以实现流量控制了。

三、获取许可

  获取许可,有非阻塞和阻塞式获取。

if (获得许可) {
    执行代码块 1
} else {
    执行代码块 2
}

  非阻塞式:尝试获取许可,如果获取到许可,则执行代码块1,如果没有获取到就认为被限流,则执行代码块2;

  阻塞式:尝试获取许可,获取到则执行代码块1,没有获取到,则阻塞,等待获取到许可后,执行代码块1,注意不会执行代码块2;

    

3.1、非阻塞获取许可

  前面使用介绍了,可以使用RateLimiter类可以使用create方法,创建多个许可,每个许可就是一个令牌,拿到令牌,才可以执行操作(通过),否则就是被限流(阻止)。

  使用tryAcquire()方法,是不阻塞的尝试获取令牌,但是他有多个重载方法,有不同的参数。

// 尝试获取1个许可,如果获取到,则返回true,否则返回false
boolean tryAcquire();

// 尝试获取多个许可,如果获取到,则返回true,否则返回false
boolean tryAcquire(int permits)
// 示例tryAcquire(3)

// 在timeout时间内,尝试获取1个许可,如果获取到,则返回true,否则返回false
tryAcquire(Duration timeout);
// 示例:tryAcquire(Duration.ofSeconds(3))
tryAcquire(long timeout, TimeUnit unit);
// 示例:tryAcquire(3, TimeUnit.SECONDS);

// 在timeout时间内,尝试获取多个许可,如果获取到,则返回true,否则返回false
tryAcquire(int permits, Duration timeout)
tryAcquire(int permits, long timeout, TimeUnit unit)

  

3.2、阻塞式获取许可

  阻塞式获取,调用的方法是acquire

package cn.ganlixin.guava;

import com.google.common.util.concurrent.RateLimiter;
import org.junit.Test;

import java.time.LocalTime;

public class UserRateLimiter {

    @Test
    public void testAcquire() {
        RateLimiter rateLimiter = RateLimiter.create(2);

        for (int i = 0; i < 10; i++) {
            double sleep = rateLimiter.acquire();
            System.out.println("now: " + LocalTime.now() + "  sleep: " + sleep);
        }
    }
}

  运行输出如下:

now: 16:59:51.879  sleep: 0.0
now: 16:59:52.289  sleep: 0.403329
now: 16:59:52.784  sleep: 0.492976
now: 16:59:53.285  sleep: 0.499409
now: 16:59:53.789  sleep: 0.498335
now: 16:59:54.285  sleep: 0.494628
now: 16:59:54.786  sleep: 0.49857
now: 16:59:55.289  sleep: 0.496816
now: 16:59:55.784  sleep: 0.494352
now: 16:59:56.288  sleep: 0.499635

  

  acquire也有重载方法:

// 尝试阻塞获取多个许可
acquire(int permits)

  

 

  

猜你喜欢

转载自www.cnblogs.com/-beyond/p/12287201.html