this.windowSize = 10;
this.queue = new LinkedList<>();
}
public boolean tryQuire() {
Long now = System.currentTimeMillis(); //获取当前时间
int counter = getQuires(now); //根据当前时间获取一秒内请求的数目
if (counter < windowSize) { //如果还没有到阈值就接受请求
queue.offer(now);
return true;
}
return false;
}
private int getQuires(Long now) {
long count = this.queue.stream().filter(item -> item > now - 1000).count();
return (int) count;
}
}
但是滑动窗口和固定窗口都无法解决短时间之内集中流量的突击。
我们所想的限流场景,例如每秒限制 100 个请求。希望请求每 10ms 来一个,这样我们的流量处理就很平滑,但是真实场景很难控制请求的频率。因此可能存在 5ms 内就打满了阈值的情况。
当然对于这种情况还是有变型处理的,例如设置多条限流规则。不仅限制每秒 100 个请求,再设置每 10ms 不超过 2 个。
漏桶算法
如下图所示,水滴持续滴入漏桶中,底部定速流出。如果水滴滴入的速率大于流出的速率,当存水超过桶的大小的时候就会溢出。
规则如下:
请求来了放入桶中
桶内请求量满了拒绝请求
服务定速从桶内拿请求处理
class water {
private int waters; //此时的水量
private int rate; //服务器消费水量的速率
private long lastTime; //上次注水时间
private int capacity; //阈值
public water() {
this.lastTime = System.currentTimeMillis();
this.rate = 1; //一毫秒消费一滴水
}
public boolean tryQuire() {
long now = System.currentTimeMillis(); //获取此时时间
int usedWaters = (int) ((now - lastTime) * rate); //计算消耗的水量
waters = Math.max(0, waters - usedWaters);
if (waters < capacity) {
lastTime = now;
waters++;
return true;
}
return false;
}
}
可以看到水滴对应的就是请求。它的特点就是宽进严出,无论请求多少,请求的速率有多大,都按照固定的速率流出,对应的就是服务按照固定的速率处理请求。
经过漏洞这么一过滤,请求就能平滑的流出,看起来很像很挺完美的?实际上它的优点也即缺点。
面对突发请求,服务的处理速度和平时是一样的,这其实不是我们想要的,在面对突发流量我们希望在系统平稳的同时,提升用户体验即能更快的处理请求,而不是和正常流量一样。
也就是说我们服务器应该可以变得灵活一点,将自己的接受能力主动的体现出来,而不是被动的去接受水桶流出来的水量。
所以就有了令牌桶算法。
令牌桶算法
令牌桶其实和漏桶的原理类似,只不过漏桶是定速地流出,而令牌桶是定速地往桶里塞入令牌,然后请求只有拿到了令牌才能通过,之后再被服务器处理。
当然令牌桶的大小也是有限制的,假设桶里的令牌满了之后,定速生成的令牌会丢弃。
规则:
定速的往桶内放入令牌
令牌数量超过桶的限制,丢弃
请求来了先向桶内索要令牌,索要成功则通过被处理,反之拒绝
class TokenBucket {
private int tokens; //此时的令牌数目
private int rate; //服务器令牌生成速率
private long lastTime; //上一次放令牌的时间
public TokenBucket(int rate) {
this.rate = rate;
this.lastTime = System.currentTimeMillis();
}
public boolean tyrQuire() {
long now = System.currentTimeMillis(); // 获取当前时间
tokens += (now - lastTime) * rate; //计算此时有多少个令牌
if (tokens > 0) {
lastTime = now;
tokens–;
return true;
}
return false;
}
}
可以看出和漏桶的区别就在于一个是加法,一个是减法。
令牌桶在应对突发流量的时候,桶内假如有 100 个令牌,那么这 100 个令牌可以马上被取走,而不像漏桶那样匀速的消费。所以在应对突发流量的时候令牌桶表现的更佳。
本质上单机限流和分布式限流的区别其实就在于 “阈值” 存放的位置。
总结
机会是留给有准备的人,大家在求职之前应该要明确自己的态度,熟悉求职流程,做好充分的准备,把一些可预见的事情做好。
对于应届毕业生来说,校招更适合你们,因为绝大部分都不会有工作经验,企业也不会有工作经验的需求。同时,你也不需要伪造高大上的实战经验,以此让自己的简历能够脱颖而出,反倒会让面试官有所怀疑。
你在大学时期应该明确自己的发展方向,如果你在大一就确定你以后想成为Java工程师,那就不要花太多的时间去学习其他的技术语言,高数之类的,不如好好想着如何夯实Java基础。下图涵盖了应届生乃至转行过来的小白要学习的Java内容:
请转发本文支持一下
。同时,你也不需要伪造高大上的实战经验,以此让自己的简历能够脱颖而出,反倒会让面试官有所怀疑。
你在大学时期应该明确自己的发展方向,如果你在大一就确定你以后想成为Java工程师,那就不要花太多的时间去学习其他的技术语言,高数之类的,不如好好想着如何夯实Java基础。下图涵盖了应届生乃至转行过来的小白要学习的Java内容:
请转发本文支持一下
[外链图片转存中…(img-cuMBTVdA-1714793400535)]
[外链图片转存中…(img-sEodKYqH-1714793400535)]