服务限流
概述
https://javaguide.cn/high-availability/limit-request.html
单机限流
Guava RateLimiter
用于控制并发请求速率的工具类,可以有效地实现限流功能。
通过RateLimiter,我们可以轻松控制系统的吞吐量,防止短时间内请求过多而导致系统过载;
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
平滑突发限流
就是按照指定的速率放令牌到桶里;
public class RateLimiterTest {
public static void main(String[] args) {
//创建一个每秒只允许发出10个令牌的RateLimiter实例
RateLimiter rateLimiter = RateLimiter.create(10.0); // 指定每秒生成令牌的数量
//模拟多个线程请求
for (int i = 0; i < 100; i++) {
// tryAcquire:不会阻塞而是立即返回是否获取令牌成功
if (rateLimiter.tryAcquire()) {
System.out.println("请求成功,时间:" + System.currentTimeMillis());
} else {
System.out.println("请求被限流,时间:" + System.currentTimeMillis());
}
}
}
}
结果:
请求成功,时间:1713167100827
请求被限流,时间:1713167100827
请求被限流,时间:1713167100827
请求被限流,时间:1713167100827
请求被限流,时间:1713167100827
请求被限流,时间:1713167100827
请求被限流,时间:1713167100827
请求被限流,时间:1713167100827
请求被限流,时间:1713167100827
请求被限流,时间:1713167100828
请求被限流,时间:1713167100828
请求被限流,时间:1713167100828
请求被限流,时间:1713167100828
请求被限流,时间:1713167100828
请求被限流,时间:1713167100828
请求被限流,时间:1713167100828
请求被限流,时间:1713167100828
请求被限流,时间:1713167100828
请求被限流,时间:1713167100828
请求被限流,时间:1713167100828
请求被限流,时间:1713167100828
请求被限流,时间:1713167100828
请求被限流,时间:1713167100828
public class RateLimiterTest {
public static void main(String[] args) {
//创建一个每秒只允许发出10个令牌的RateLimiter实例
RateLimiter rateLimiter = RateLimiter.create(10.0); // 指定每秒生成令牌的数量
for (int i = 0; i < 100; i++) {
// acquire()方法尝试获取一个令牌,如果令牌桶中有足够的令牌,则立即返回;否则,阻塞等待直到有足够的令牌
double acquire = rateLimiter.acquire();
System.out.println("请求成功,时间:" + System.currentTimeMillis());
}
}
}
结果:
请求成功,时间:1713167182646
请求成功,时间:1713167182746
请求成功,时间:1713167182847
请求成功,时间:1713167182949
请求成功,时间:1713167183046
请求成功,时间:1713167183147
请求成功,时间:1713167183248
请求成功,时间:1713167183346
请求成功,时间:1713167183446
请求成功,时间:1713167183545
请求成功,时间:1713167183647
平滑预热限流
预热时间之内,速率会逐渐提升到配置的速率;
public class RateLimiterTest {
public static void main(String[] args) {
// 创建一个每秒只能发出5个令牌的实例
// 预热时间为3s,也就说刚开始的 3s 内发牌速率会逐渐提升到 0.2s 放 1 个令牌到桶里
RateLimiter rateLimiter = RateLimiter.create(5, 3, TimeUnit.SECONDS);
for (int i = 0; i < 200; i++) {
double sleepingTime = rateLimiter.acquire(1);
System.out.printf("get 1 tokens: %sds%n", sleepingTime);
}
}
}
结果:
get 1 tokens: 0.0ds
get 1 tokens: 0.545473ds
get 1 tokens: 0.512818ds
get 1 tokens: 0.464959ds
get 1 tokens: 0.412942ds
get 1 tokens: 0.355748ds
get 1 tokens: 0.305462ds
get 1 tokens: 0.2494ds
get 1 tokens: 0.203677ds
get 1 tokens: 0.196401ds
get 1 tokens: 0.200042ds
get 1 tokens: 0.198179ds
get 1 tokens: 0.195615ds
get 1 tokens: 0.196237ds
get 1 tokens: 0.197006ds
get 1 tokens: 0.195847ds
get 1 tokens: 0.198456ds
get 1 tokens: 0.195293ds
get 1 tokens: 0.195719ds
get 1 tokens: 0.194725ds
浙公网安备 33010602011771号