RateLimiter速率了解

RateLimiter

pom 复制代码
<dependency>
	<groupId>com.google.guava</groupId>
	<artifactId>guava</artifactId>
	<version>22.0</version>
</dependency>

这个同名的类在nacos的jar包中也有出现。速率限制于java.util.concurrent.Semaphore功能相反,后者限制并发的访问数量,而不是速率(并发和速率密切相关)。见下面的Little定律

RateLimiter主要由颁发许可证的速率来定义。如果没有额外的配置,许可证将以固定的速率分配,以每秒的许可证定义。许可证将顺利分配,并调整各个许可证之间的延迟,以确保维持配置的费率。可以将RateLimiter配置为有一个预热期,在此期间,每秒发出的许可稳步增加,直到达到稳定的速率。

例如:任务每秒执行不超过2次

java 复制代码
final RateLimiter rateLimiter = RateLimiter.create(2.0); // 速率为"每秒2次许可"
void submitTasks(List<Runnable> tasks, Executor executor) {    
	for (Runnable task : tasks) {      
		rateLimiter.acquire(); // 等待
		executor.execute(task);    
	}  
}

例如:发送一个数据流,控制其速度在每秒为5kb,可以通过每个自己一个许可实现,并指定每秒5000个许可的速率

java 复制代码
final RateLimiter rateLimiter = RateLimiter.create(5000.0); // rate = 5000 permits per second  
void submitPacket(byte[] packet) {    
	rateLimiter.acquire(packet.length);    
	networkService.send(packet);  
}

for循环每秒打印一行,RateLimiter.create(1000);为什么会这样:

应为速率是指定为1000次/秒(类似频率),这个时候你一次要获取1000个凭证,因为这个会阻塞当前获取,所以你要算什么时候能获取到所有凭证的时间为:所需凭证数(1000)÷速率(1000次/秒) = 1秒

java 复制代码
public class TestRateLimiter {

    private static final Logger log = LoggerFactory.getLogger(PostExecutor.class);

    public static void main(String[] args) {
    	// 每秒最多允许1000个操作(每秒只能发送1000个凭证)
        RateLimiter limiter = RateLimiter.create(1000);
        log.info("start");
        for (int i = 0; i < 10; i++) {
        	// 获取1000个凭证,获取不到则等待
            limiter.acquire(1000);
            log.info("I: " + i);
        }
    }
}

在一定时间内获取对应的凭证 ,超时获取不到结束

java 复制代码
private static void tryAcquireTest1(RateLimiter limiter, int i){
	log.info("result: " + limiter.tryAcquire(20, 20000, TimeUnit.MILLISECONDS) + ", " + i);
}


这里的速率是2次每秒,可是我阻塞事件获取20个凭证,意味着10s执行一次,在多线程竞争的情况下,有一个线程多次false结束而且时间也没有达到20s(猜测是不是因为其他两个线程一共获取了40个凭证,意味着这20s之内不会再有新凭证了,所以他就不会非要等到20s才结束获取凭证,就提前结束了),启动两个线程,发现就会交替输出了,但是也出现了多次false的情况

java 复制代码
public class TestRateLimiter {

    private static final Logger log = LoggerFactory.getLogger(PostExecutor.class);

    public static void main(String[] args) {
        RateLimiter limiter = RateLimiter.create(2);
        log.info("start");
        
        Thread t1 = new Thread(()->{tryAcquireTest(limiter);});
        Thread t2 = new Thread(()->{tryAcquireTest(limiter);});
        Thread t3 = new Thread(()->{tryAcquireTest(limiter);});
        t1.start();
        t2.start();
        t3.start();

    }

    private static void tryAcquireTest(RateLimiter limiter){
        for (int i = 0; i < 10; i++) {
            tryAcquireTest1(limiter,i);
        }
    }

    private static void tryAcquireTest1(RateLimiter limiter, int i){
        log.info(Thread.currentThread().getName() + "result: " + limiter.tryAcquire(20, 20000, TimeUnit.MILLISECONDS) + ", " + i);
    }
}




相关推荐
a程序小傲9 分钟前
米哈游Java面试被问:gRPC的HTTP/2流控制和消息分帧
java·开发语言·tcp/ip·http·面试·职场和发展·php
新缸中之脑16 分钟前
学习AI编程 vs. 学习编程
java·学习·ai编程
试剂小课堂 Pro25 分钟前
Ald-PEG-Ald:丙醛与聚乙二醇两端连接的对称分子
java·c语言·c++·python·ffmpeg
独自破碎E25 分钟前
【双指针】接雨水
java·开发语言
AllData公司负责人26 分钟前
【亲测好用】数据平台能力演示
java·数据库·c++·开源
0和1的舞者28 分钟前
技术优化手册:从工具类到 MyBatis 配置与业务逻辑
java·后端·学习·开发·知识
若鱼191929 分钟前
SpringBoot4.0新特性-Resilience之并发限制
java·spring
砚边数影36 分钟前
逻辑回归实战(二):Java + DL4J 实现模型,评估指标(准确率/召回率)计算
java·数据库·算法·机器学习·逻辑回归·金仓数据库
Cher ~37 分钟前
【数据结构】hash表(unordered_map)
java·数据结构·c++·算法·哈希算法
zfj32144 分钟前
好书分享:《两周自制脚本语言》-用java实现一个脚本语言
java·开发语言·python·编译原理