RateLimiter
RateLimiter
是 Guava 库中的一个类,用于实现限流功能。它基于令牌桶算法,通过控制生成和消费令牌的速率来限制对某个资源的访问频率。
主要作用是控制对资源的访问速率,可以限制每秒访问的请求数量或每秒处理的任务数量,以避免资源被过度使用或超负荷运行。
使用 RateLimiter
可以实现以下功能:
- 平滑限流:
RateLimiter
可以根据设定的速率,以平滑的方式限制对资源的访问。它可以确保访问速率平稳,并且在突发流量下也能控制访问频率,避免资源被过度耗尽。 - 非阻塞限流:
RateLimiter
采用非阻塞的方式进行限流,不会阻塞等待请求或任务的执行。它通过返回一个等待时间,让调用方自行决定是否等待,以控制访问频率。
通过适当配置 RateLimiter
的速率参数,可以灵活地控制对资源的访问速率,从而实现对系统的流量控制。
package com.example.common.util;
import com.google.common.util.concurrent.RateLimiter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* RateLimiter -- 限流
* 定时任务 -- 轮询扫描法
*
* @author wanglizhi
* @date 2023/7/17 14:01
*/
@Component
public class CurrentLimiter {
/**
* 定义限流器
*/
private final static RateLimiter RATE_LIMITER = RateLimiter.create(1);
private Integer pointer = 0;
@Autowired
@Qualifier(value = "systemExecutor")
Executor executor;
// @PostConstruct
public void main() {
for (int i = 0; i < 5; i++) {
executor.execute(() -> {
System.out.println(Thread.currentThread().getName());
RATE_LIMITER.acquire();
System.out.println(new Date());
});
}
}
/**
* 轮询扫描法 -- 使用Timer(ali建议使用ScheduledExecutorService代替Timer)
*/
// @PostConstruct
public void pollingScanningMethod() {
Timer timer = new Timer();
List<Map<Integer, String>> list = new ArrayList<>(10);
for (int i = 0; i < 10; i++) {
Map<Integer, String> map = new HashMap<>();
for (int j = 0; j < 10; j++) {
map.put(j, String.valueOf(j));
}
list.add(map);
}
// 创建一个定时任务
TimerTask task = new TimerTask() {
@Override
public synchronized void run() {
List<Integer> removeKey = new ArrayList<>();
// 在这里定义需要执行的任务逻辑
list.get(pointer).forEach((key, value) -> {
if (key % 2 == 0) {
removeKey.add(key);
}
});
removeKey.forEach(key -> {
list.get(pointer).remove(key);
System.out.println("删除--" + "pointer:" + pointer + "key:" + key);
});
if (pointer < 9) {
pointer++;
} else {
pointer = 0;
}
}
};
// 启动定时器,每隔一定时间执行任务
timer.schedule(task, 0, 1000); // 在0毫秒后开始执行任务,每隔1000毫秒重复执行
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list);
// 停止定时器
timer.cancel();
}
/**
* 轮询扫描法 --使用ScheduledExecutorService
*/
@PostConstruct
public void pollingScanningMethod1() {
List<Map<Integer, String>> list = new ArrayList<>(10);
for (int i = 0; i < 10; i++) {
Map<Integer, String> map = new HashMap<>();
for (int j = 0; j < 10; j++) {
map.put(j, String.valueOf(j));
}
list.add(map);
}
// 创建一个 ScheduledExecutorService
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
Runnable task = () -> {
List<Integer> removeKey = new ArrayList<>();
list.get(pointer).forEach((key, value) -> {
if (key % 2 == 0) {
removeKey.add(key);
}
});
removeKey.forEach(key -> {
list.get(pointer).remove(key);
System.out.println("删除--" + "pointer:" + pointer + "key:" + key);
});
if (pointer < 9) {
pointer++;
} else {
pointer = 0;
}
};
// 启动定时器,每隔一定时间执行任务
executor.scheduleWithFixedDelay(task, 0, 1, TimeUnit.SECONDS);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list);
// 停止定时器
executor.shutdown();
}
}