漏桶算法
将流量都放到漏桶中,漏桶以一定的速率出水,当进入的流量大于出水流量,就会将多余的水存储在桶中,强行限制流量请求量
桶容量:最大并发数,如果桶满了,后续想要进入的请求就无法再存放到桶中,多余的请求就会被丢弃。
这个和利用消息队列的削峰的思路类似,利用队列消费速度,将生产的消息通过稳定的速率进行消费,多与的消息会存放在队列中等待消费.
缺点:无法面对突发的大流量,一旦超过桶的上限,其他请求全部拒绝。
思路:
1.当请求进入时,先判断桶中的流量是否已满,如果未满,就进入,如果已满,就拒绝进入
2.流出时,刷新桶中的实时容量和刷新时间
简单手动线程测试
1.定义常量
- 最大容量
- 流出速率
- 当前时间(用于判断请求是否可以进入)
- 更新时间(当指定时间刷新时,需要当前时间减去上次更新时间来确认流出了多少请求)
Controller实现
当初始化进入第一个请求时,需要刷新更新时间,否则会瞬间清空桶容量。
先执行减去操作,提高容量的时效性。再执行判断增加操作。
public boolean allow(String request) {
// 初始化接收请求时,更新时间
if (this.currentCapacity == 0) {
this.refrshTime = System.currentTimeMillis();
}
// 先执行刷新操作,可以先提高容量的时效性
long now = System.currentTimeMillis();
// 刷新当前容量
this.currentCapacity = Math.toIntExact(Math.max(0, this.currentCapacity - ((now - this.refrshTime) / 1000 * this.outSpeed)));
this.refrshTime = now;
// 容量已满,拒绝访问
if (this.currentCapacity >= this.capacity) {
System.out.println("满了");
return false;
}
this.currentCapacity ++;
this.requestQueue.add(request);
return true;
}
将限流功能集成到请求中
@PostMapping("/lt")
public String lt(HttpServletRequestrequest) {
if(lt.allow(Long.toString(System.currentTimeMillis()))) {
//调用接口
}
return "请稍后再试";
}