艺术~在单机和分布式环境下的限流算法(漏桶算法、令牌桶算法)

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)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值