漏桶算法和令牌桶算法

目录

一、漏桶(Leaky Bucket)

简易实现:

效果:

二、令牌桶算法

简易实现:

效果:

两种算法对比:


一、漏桶(Leaky Bucket)

        算法思路简单,水(请求)先进入到漏桶中,漏桶以一定的速度出水(接口有响应速率),当水流速度过大直接溢出(访问频率超过接口响应频率),然后就拒绝请求,可以看出漏桶算法能强制限制数据的传输速率。

假设我们有一个桶,我们希望以随机的速率向桶中倒水,并以恒定的速率从桶中取水。因此我们需要在桶底部打一个固定大小的洞,这样来保证水流处的速率是恒定的。由于桶的体积有限,因此倒满后就停止。

水流入的速率可以改变,但输出的速率是恒定的。这种平滑输出流量的方法称为漏桶技术。突发进入的流量存储在桶中,并以稳定的速率输出。

简易实现:

package com.suanfa;

public class test2 {
    //漏桶算法
    public static void main(String[] args) {
        //t1,t2线程每1秒往桶里添加一个请求
        Bucket bucket=new Bucket(0);
        Thread t1=new Thread(bucket);
        Thread t2=new Thread(bucket);
        //t3线程恒定速度处理请求
        Thread t3=new Thread(new Handle(bucket));

        t1.start();
        t2.start();
        t3.start();
    }
}
class Bucket implements Runnable{
    int max=20;//桶的最大容量
    int num;//请求数
    Bucket(int num){
        this.num=num;
    }
    @Override
    public void run() {
        while (true){
            synchronized (this){
                if (num>=max){
                    System.out.println("桶的容量满了,该请求被丢失");
                }else {
                    num++;
                    System.out.println("往桶里添加一个请求,目前有"+num+"个请求");
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
//处理请求
class Handle implements Runnable{
    Bucket b;
    Handle(Bucket b){
        this.b=b;
    }
    @Override
    public void run() {
        while (true){
            synchronized (b){
                if (b.num>0){
                    b.num--;
                    System.out.println("已处理一个请求,目前还剩"+b.num+"个请求");
                }else {
                    System.out.println("桶已空,不需要处理请求");
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

效果:

        桶中请求数有限制,满了则丢弃,桶以一定速度处理请求

二、令牌桶算法

        令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。

令牌桶算法和漏桶算法不同的是,有时后端能够处理一定的突发情况,只是为了系统稳定,一般不会让请求超过正常情况的60%,给容灾留有余地。但漏桶算法中后端处理速度是固定的,对于短时的突发情况,后端不能及时处理,和实际处理能力不匹配。

令牌算法是以固定速度往一个桶内增加令牌,当桶内令牌满了后,就停止增加令牌。上游请求时,先从桶里拿一个令牌,后端只服务有令牌的请求,所以后端处理速度不一定是匀速的。当有突发请求过来时,如果令牌桶是满的,则会瞬间消耗桶中存量的令牌。如果令牌还不够,那么再等待发放令牌(固定速度),这样就导致处理请求的速度超过发放令牌的速度。
 

简易实现:

package com.suanfa;

public class test{

    //令牌桶算法

    public static void main(String[] args) {
        Token t=new Token(20);//初始20个
        //t1每秒往桶里放令牌
        Thread t1=new Thread(t);

        //t3,t4模拟请求,处理一个请求需要从桶里获取一个
        // 令牌,没有令牌,就丢弃
        Thread t3=new Thread(new Use("a",t));
        Thread t4=new Thread(new Use("b",t));

        t1.start();
        t3.start();
        t4.start();


    }
}
//往桶里放令牌
class Token implements Runnable {
    //令牌数
    int token;
    Token(int token){
        this.token=token;
    }
    @Override
    public void run() {
        while(true){
            synchronized (this){

                token++;
                System.out.println("往桶里放一个令牌,目前共有"+token+"个令牌");

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }


}
class Use implements Runnable {
    //请求名
    String name;
    Token t;
    Use(String name,Token t){
        this.t=t;
        this.name=name;
    }
    @Override
    public void run() {
        while(true){
            synchronized (t){
                if (t.token>0){
                    t.token--;
                    System.out.println(name+"在桶里获取1个令牌,还剩"+t.token+"个令牌");
                }else {
                    System.out.println("目前桶里无令牌,请求失效");
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

效果:

        处理请求需要令牌,没有令牌则丢弃该请求

两种算法对比:

        漏桶算法通常可以用于限制访问外部接口的流量,保护其他人系统,比如我们请求银行接口,通常要限制并发数。

        令牌桶算法生成令牌的速度是恒定的,而请求去拿令牌是没有速度限制的。这意味,面对瞬时大流量,该算法可以在短时间内请求拿到大量令牌,可以处理瞬时流量,而且拿令牌的过程并不是消耗很大的事情。令牌桶算法通常可以用于限制被访问的流量,保护自身系统。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值