1.计数限流算法实现
bash
public class CounterLimiter {
private Long timeStamp = System.currentTimeMillis();
//请求次数
private int reqCount;
//每秒限流的最大请求书
private int limitNum = 100;
//时间间隔
private Long interval = 1000L;
/***
* @Description
* @Param []
* @Return java.lang.Boolean 返回true代表限流,false代表通过
**/
public synchronized Boolean limit(){
Long now = System.currentTimeMillis();
if(now < timeStamp + interval){
if(reqCount + 1 > limitNum){
return true;
}
reqCount++;
return false;
}else{
timeStamp = now;
reqCount = 1;
return false;
}
}
}
2.滑动窗口限流算法实现
bash
public class SlidingTimeWindowLimiter {
//请求计数器
private int reqCount;
//使用LinkedList来记录滑动窗口的10个格子
private LinkedList<Integer> slots = new LinkedList<>();
//每秒限流的最大请求数
private int limitNum = 100;
//滑动窗口每个格子的时间长度,单位ms
private long windowLength = 100;
//滑动窗口的格子数量
private int windowNum = 10;
public synchronized Boolean limit(){
if(reqCount + 1 > limitNum){
return true;
}
slots.set(slots.size() - 1, slots.peekLast() + 1);
reqCount++;
return false;
}
public SlidingTimeWindowLimiter() {
slots.add(0);
new Thread(() -> {
while (true) {
try{
TimeUnit.MILLISECONDS.sleep(windowLength);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
synchronized (this) {
//滑动窗口
slots.add(0);
if(slots.size() > windowNum){
reqCount -= slots.peekFirst();
slots.removeFirst();
}
}
}
}).start();
}
}
3.漏桶限流算法实现
bash
public class LeakyBucketLimiter {
private long timeStamp = System.currentTimeMillis();
//桶的容量
private long capacity = 100;
//水漏的速度(每秒系统能处理的请求数)
private long rate = 10;
//当前水量(当前积累请求书)
private long water = 0;
public synchronized Boolean limit(){
long now = System.currentTimeMillis();
water = Math.max(0, (now - timeStamp)/1000 * rate);
timeStamp = now;
if(water + 1 <= capacity){
water++;
return false;
}else {
//水满,拒绝加水
return true;
}
}
}
4.令牌桶限流算法实现
bash
public class TokenBucketLimiter {
private long timeStamp = System.currentTimeMillis();
//桶的容量
private long capacity = 100;
//水漏的速度(每秒系统能处理的请求数)
private long rate = 10;
//当前水量(当前积累请求书)
private long tokens = 100;
public synchronized Boolean limit(){
long now = System.currentTimeMillis();
//先添加令牌
tokens = Math.min(capacity, tokens + (now - timeStamp)/1000 * rate);
timeStamp = now;
if(tokens - 1 > 0){
return true;
}
//领取令牌
tokens --;
return false;
}
}