限流算法-漏桶算法| 8月更文挑战

1,041 阅读2分钟

漏桶算法

Untitled.png

将流量都放到漏桶中,漏桶以一定的速率出水,当进入的流量大于出水流量,就会将多余的水存储在桶中,强行限制流量请求量

桶容量:最大并发数,如果桶满了,后续想要进入的请求就无法再存放到桶中,多余的请求就会被丢弃。

这个和利用消息队列的削峰的思路类似,利用队列消费速度,将生产的消息通过稳定的速率进行消费,多与的消息会存放在队列中等待消费.

缺点:无法面对突发的大流量,一旦超过桶的上限,其他请求全部拒绝。

1.png

思路:

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 "请稍后再试";
}