原理可以看下https://zhuanlan.zhihu.com/p/60979444 这位大哥讲的, 感觉讲的很清楚,
反正基本就是木桶算法, 简单就是,
相当于一个柜台里, 你规定好每秒往里边放10(几)块蛋糕, 这样限流的配置就已经做完了
对于使用上, 用户过来调用你的方法, 请求你的资源, 他来一次, 拿走一块蛋糕, 假如来了十个人, 一秒抢光,
第十一个人等, 再来拿, 就不管他了, 当他没来过, (当然你肯定得自定义的告诉他一个提示: 限流了), 需要
注意的是,
1, 每个人拿多少蛋糕是可以设置的, 比如说, 我第一个人直接要9快蛋糕, 第二个人要1快, 第三个人也要1快, 虽然说, 第三个人要的比较少, 但是也达到了阈值, 第三个人仍然会被抛弃
2, 测试期间, 如果你debug在第一个异步任务, 看着是断点了, 但是如果经过1秒了, 他又会重新颁发蛋糕, 因此有时候会出现这样的效果, jiekou1的Limiter设置了2个, 但是debug停止了一下, 结果三个异步任务都tryAcquire都是true, 都获取到了蛋糕, 因此我这边测试就加了一个sleep, 等待static systemRate真正的初始化完成后, 客户再开始抢蛋糕
3, 当然还有一些初始化参数的配置, 比如设置预热, 设置时分秒单位啥的, 就看具体需求,具体配置了
测试:
@Slf4j
public class Test {
private static ConcurrentHashMap<String, RateLimiter> systemRate = new ConcurrentHashMap<>();
static {
systemRate.put("jiekou1", RateLimiter.create(10));
systemRate.put("jiekou2", RateLimiter.create(4));
}
public static boolean tt(String key ,int count){
return systemRate.get("jiekou1").tryAcquire(count);
}
public static void main(String[] args) throws InterruptedException {
Thread.sleep(600);
AtomicInteger i = new AtomicInteger();
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
boolean jiekou1 = tt("jiekou1",3);
log.info("111 >>>:{}",jiekou1);
if (jiekou1) {
log.info("运行" + (i.incrementAndGet()) + "次");
}
});
CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
boolean jiekou1 = tt("jiekou1",3);
log.info("222 >>>:{}",jiekou1);
if (jiekou1) {
log.info("运行" + (i.incrementAndGet()) + "次");
}
});
CompletableFuture<Void> future3 = CompletableFuture.runAsync(() -> {
boolean jiekou1 = tt("jiekou1",3);
log.info("333 >>>:{}",jiekou1);
if (jiekou1) {
log.info("运行" + (i.incrementAndGet()) + "次");
}
});
try {
CompletableFuture.allOf(future,future2,future3).get();
} catch (Exception e) {
e.printStackTrace();
}
}
}