Spring Boot 接口如何做限流?
前言
算法介紹
計數器法
public class CounterDemo {
public long timeStamp = getNowTime();
public int reqCount = 0;
public final int limit = 100; // 時間窗口內最大請求數
public final long interval = 60000; // 時間窗口ms
public boolean grant() {
long now = getNowTime();
if (now < timeStamp + interval) {
// 在時間窗口內
reqCount++;
// 判斷當前時間窗口內是否超過最大請求控制數
return reqCount <= limit;
}
else {
timeStamp = now;
// 超時后重置
reqCount = 1;
return true;
}
}
private static Long getNowTime(){
return System.currentTimeMillis();
}
}
滑動窗口
public class CounterDemo {
public long timeStamp = getNowTime();
public int reqCount = 0;
public final int limit = 100; // 時間窗口內最大請求數
public final long interval = 6000; // 時間窗口6ms,6格
public boolean grant() {
long now = getNowTime();
if (now < timeStamp + interval) {
// 在時間窗口內
reqCount++;
// 判斷當前時間窗口內是否超過最大請求控制數
return reqCount <= limit;
}
else {
timeStamp = now;
// 超時后重置
reqCount = 1;
return true;
}
}
private static Long getNowTime(){
return System.currentTimeMillis();
}
}漏桶算法
public class LeakyDemo {
public long timeStamp = getNowTime();
public int capacity; // 桶的容量
public int rate; // 水漏出的速度
public Long water; // 當前水量(當前累積請求數)
public boolean grant() {
long now = getNowTime();
water = Math.max(0L, water - (now - timeStamp) * rate); // 先執(zhí)行漏水,計算剩余水量
timeStamp = now;
if ((water + 1) < capacity) {
// 嘗試加水,并且水還未滿
water += 1;
return true;
}
else {
// 水滿,拒絕加水
return false;
}
}
private static Long getNowTime(){
return System.currentTimeMillis();
}
}令牌桶算法
public class TokenBucketDemo {
public long timeStamp = getNowTime();
public int capacity; // 桶的容量
public int rate; // 令牌放入速度
public Long tokens; // 當前令牌數量
public boolean grant() {
long now = getNowTime();
// 先添加令牌
tokens = Math.min(capacity, tokens + (now - timeStamp) * rate);
timeStamp = now;
if (tokens < 1) {
// 若不到1個令牌,則拒絕
return false;
}
else {
// 還有令牌,領取令牌
tokens -= 1;
return true;
}
}
private static Long getNowTime(){
return System.currentTimeMillis();
}
}RateLimiter實現
@Slf4j
public class RateLimiterExample1 {
// 代表每秒最多2個
// guava限流采用的是令牌桶的方式
private static RateLimiter rateLimiter = RateLimiter.create(2);
public static void main(String[] args) {
for (int index = 0; index < 100; index++) {
// 單位時間內獲取令牌
if (rateLimiter.tryAcquire(190, TimeUnit.MILLISECONDS)) {
handle(index);
}
}
}
private static void handle(int i) {
log.info("{}", i);
}總結
計數器 VS 滑動窗口
漏桶算法 VS 令牌桶算法
作者 | bruce.yao
來源 | blog.csdn.net/yb223731/article/details/95460376

評論
圖片
表情






