限流之漏桶算法

        现在,微服务大行其道,好多项目都是拆分,再拆分,美其名曰:解耦!这个不多说,适合自己的实际项目就好,反正项目都是会逐渐演进。

        不过,无论哪种服务,一旦用户量大了,请求多了,服务器压力就会很大,有时候,可能直接把服务器搞崩溃了。于是,我们常用的一些中间件或者是一些策略方法,便进入到了项目之中。比如:消息中间件的削峰填谷,布隆过滤器的拦截鉴定,Nginx的轮询转发等等等等。
       今天,就来说一个中间件常用的限流算法,木桶算法!

      简单描述一下,其实也就是类比。还记得小时候的数学题么?一个游泳池里面,一个管道放水,一个抽水机抽水,管道放水的速度是多少,抽水机抽水的速度是多少,然后,什么时候游泳池会被放满水之类的。

         

        漏桶算法,和这个类似,就是把流量比作水流,流量现进入到木桶中,然后木桶下面有一个洞,当然,洞的大小(流速)可以自己控制。这样就可以防止流量蜂拥而至,压垮服务器。

       客户端发送请求,先要进入木桶中,短暂缓存后,从木桶的洞口周流出。这样就可以保证流量的匀速性,减少服务器的压力。

        那如果木桶满了呢?满了,就拒绝呗!再多就hold不住了,那你等会再来呗~

        下面简单的看下木桶算法,上个简单代码。

import java.util.Random;
import java.util.concurrent.*;

/**
 * desc: 漏桶算法
 * author:zhang
 */
public class BucketTest {

    // 漏桶算法,桶其实就是一个缓存,一个计数(相当于多少滴水),简单点,直接存个数字吧
    private static volatile long bucket = 666 ;
    // 初始化,刚开始桶里没有水(0滴)
    private static long water = 0 ;
    // 速度,滴6滴水/s.这个是水桶自动的. 本来想定毫秒的,太快了。。
    private static long rate = 6 ;

    private static CountDownLatch countDownLatch = new CountDownLatch(1);

    public static void main(String[] args) throws InterruptedException {

        long start = System.currentTimeMillis();
        //启动一个定时器吧,2个线程的
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
        //线程任务是加水,200毫秒加一次
        executor.scheduleAtFixedRate(() -> {
            //先定义下加多少水吧,水量肯定是随机的,定一个呗
            Random random = new Random();
            int addWater = random.nextInt(500);
            System.out.println("加水量:"+addWater);
            //看下桶里还有多少水呗,满了就不给装了。这个时候就用到了二年级知识了,速率*时间 = 水量。
            //哦,水量不能是负值,限制下
            water = Math.max(0, water - (System.currentTimeMillis()-start) * rate/1000);
            if ((water + addWater) > bucket) {
                //水溢出了,肯定要结束啊,不阻塞了
                System.out.println("水满了");
                countDownLatch.countDown();
            } else {
                System.out.println("水量:"+water + ",继续加水!");
                water = water + addWater;
            }

        },  0,200,TimeUnit.MICROSECONDS);

        // 阻塞线程
        countDownLatch.await();
        // 这个之前漏掉了,主线程关闭,定时器并没有关掉
        executor.shutdownNow();
    }

}

 我这个加水还是有点慢,加了好久才结束,本地调试的时候,可以改下addWater,调大一下数字,这样就会快点结束。

看下结果哈~

 no sacrifice,no victory~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

笔下天地宽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值