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

1,884 阅读2分钟

令牌桶

限制的是平均流入速率。令牌桶算法在突发情况下,处理速率可以超过限制。算是漏桶的改进版,能够防止一定程度的流量突发。突发流量大于生成速率但是小于桶的容量,也是能够接受的。

原理:

  • 令牌桶会存放一定数量的令牌(令牌桶装的是令牌,不是流量),一个请求通过会消耗一个令牌。桶中没有令牌时,就无法通过任何数据。
  • 为了接口保证能通过数据,就需要往桶里增加令牌。增加令牌的速度决定了流量通过的速度,这一点和漏桶类似。
  • 当有流量进入令牌桶时,需要拥有对应数量的令牌才能通过,如果没有,该请求就会被拒绝。
  • 由于令牌桶有存量,可以防止一定程度的流量突发,只要平均速率在合理控制范围内就可以接受。

实现

参数

  • 令牌产生速率
  • 更新时间(用于计算令牌产生数量)
  • 桶容量
  • 当前令牌数量
// 令牌生速率
    private int speed = 1;

    // 更新时间
    private long updateTime;

    // 桶容量
    private int capacity = 100;

    // 当前令牌数量
    public int num;

方法

当流量进入时,先更新当前时间的令牌数量。如果令牌数量足够,就消耗令牌,通过。

public String filter(int permit) {
/*先结算令牌数量*/
long now = System.currentTimeMillis();
//上限为桶容量,超过就丢弃
long time = (now -this.updateTime) / 1000;
this.num = Math.toIntExact(Math.min(capacity,this.num + time * speed));
this.updateTime = now;
String message = "当前令牌数:"+this.num+",需要令牌数"+permit;
if(this.num < permit) {
        String error = message+",请求拒绝================";
        System.out.println(message);
return error;
    }
else{
        System.out.println(message);
this.num =this.num - permit;
return message;
    }

与漏桶的比较

存放对象

  1. 漏桶存放的是请求量,当请求速率大于通过速率,多余的请求就会存放到漏桶中。
  2. 令牌桶存放的是令牌量,生成的令牌都会放入令牌桶中被消耗。如果令牌的数量已满,就会丢弃多余的令牌。

限制方法

  1. 以流出速率限制流量。被限制的流量会保存在漏桶中,以便平缓通过。桶中存满后多余流量会被拒绝。
  2. 以令牌产生速率限制流量。流量通过时需要消耗对应数量的令牌才能通过,那么令牌产生的速率小于流量通过的速率,就能限制流量。多余的流量(没有令牌可以消耗)会被缓存或者丢弃。