public class FixedWindowRateLimiter {
private long windowSize; // 时间窗口大小,单位毫秒
private int maxRequestCount; // 允许通过请求数
private AtomicInteger count = new AtomicInteger(0); // 当前窗口通过的请求计数
private long windowBorder; // 窗口右边界
public FixedWindowRateLimiter(long windowSize, int maxRequestCount) {
this.windowSize = windowSize;
this.maxRequestCount = maxRequestCount;
windowBorder = System.currentTimeMillis() + windowSize;
}
public synchronized boolean tryAcquire() {
long currentTime = System.currentTimeMillis();
if (windowBorder < currentTime) {
windowBorder += windowSize;
count.set(0);
}
if (count.intValue() < maxRequestCount) {
count.incrementAndGet();
return true;
} else {
return false;
}
}
}
public class SlidingWindowRateLimiter {
private long windowSize; // 时间窗口大小,单位毫秒
private int shardNum; // 分片窗口数
private int maxRequestCount; // 允许通过请求数
private int[] shardRequestCount; // 各个窗口内请求计数
private int totalCount; // 请求总数
private int shardId; // 当前窗口下标
private long tinyWindowSize; // 每个小窗口大小,毫秒
private long windowBorder; // 窗口右边界
public SlidingWindowRateLimiter(long windowSize, int shardNum, int maxRequestCount) {
this.windowSize = windowSize;
this.shardNum = shardNum;
this.maxRequestCount = maxRequestCount;
shardRequestCount = new int[shardNum];
tinyWindowSize = windowSize / shardNum;
windowBorder = System.currentTimeMillis();
}
public synchronized boolean tryAcquire() {
long currentTime = System.currentTimeMillis();
if (currentTime > windowBorder) {
do {
shardId = (++shardId) % shardNum;
totalCount -= shardRequestCount[shardId];
shardRequestCount[shardId] = 0;
windowBorder += tinyWindowSize;
} while (windowBorder < currentTime);
}
if (totalCount < maxRequestCount) {
shardRequestCount[shardId]++;
totalCount++;
return true;
} else {
return false;
}
}
}
public class LeakyBucketRateLimiter {
private int capacity; // 桶的容量
private AtomicInteger water = new AtomicInteger(0); // 桶中现存水量
private long leakTimeStamp; // 开始漏水时间
private int leakRate; // 水流出的速率,即每秒允许通过的请求数
public LeakyBucketRateLimiter(int capacity, int leakRate) {
this.capacity = capacity;
this.leakRate = leakRate;
}
public synchronized boolean tryAcquire() {
if (water.get() == 0) {
leakTimeStamp = System.currentTimeMillis();
water.incrementAndGet();
return water.get() < capacity;
}
long currentTime = System.currentTimeMillis();
int leakedWater = (int)((currentTime - leakTimeStamp) / 1000 * leakRate);
if (leakedWater != 0) {
int leftWater = water.get() - leakedWater;
water.set(Math.max(0, leftWater));
leakTimeStamp = System.currentTimeMillis();
}
if (water.get() < capacity) {
water.incrementAndGet();
return true;
} else {
return false;
}
}
}
RateLimiter rateLimiter = RateLimiter.create(5);
for (int i = 0; i < 10; i++) {
double time = rateLimiter.acquire();
System.out.println("等待时间:" + time + "s");
}
@Service
public class QueryService {
public static final String KEY = "query";
@SentinelResource(value = KEY, blockHandler = "blockHandlerMethod")
public String query(String name) {
return "begin query, name=" + name;
}
public String blockHandlerMethod(String name, BlockException e) {
e.printStackTrace();
return "blockHandlerMethod for Query : " + name;
}
}
@Component
public class PathKeyResolver implements KeyResolver {
public Mono<String> resolve(ServerWebExchange exchange) {
String path = exchange.getRequest().getPath().toString();
return Mono.just(path);
}
}
限流是确保系统稳定性的关键措施之一。文章介绍了六种限流方法,包括固定窗口算法、滑动窗口算法、漏桶算法、令牌桶算法、中间件限流和网关限流,各有优缺点,适用于不同的场景和架构。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。