<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          令牌桶限流算法應(yīng)用

          共 1282字,需瀏覽 3分鐘

           ·

          2021-11-03 22:55

          前言

          今天原本是要出一個(gè)令牌桶限流算法的web應(yīng)用demo的,但是實(shí)際在搜索和實(shí)現(xiàn)相關(guān)算法的時(shí)候,發(fā)現(xiàn)似乎實(shí)現(xiàn)都不理想,于是我就花費(fèi)了大量的實(shí)踐用來尋找合適的限流算法,所以也就沒有足夠的時(shí)間來完成相關(guān)demo了,我不過我這里可以分享下思路,結(jié)合我們昨天和前天分享的內(nèi)容,我想各位小伙伴應(yīng)該能夠自己做出來:

          令牌桶限流依然是在攔截器層實(shí)現(xiàn),定義一個(gè)令牌桶限流注解,注解中定義速率和令牌桶容量,然后在攔截中獲取接口方法注解,實(shí)例化限流算法示例,調(diào)用限流算法acquire方法獲取token,如果token獲取失敗,則表示目前沒有可用令牌(觸發(fā)限流機(jī)制),直接返回錯(cuò)誤信息,如果獲取到token,直接進(jìn)入到接口中。

          下面我們看下今天我這邊搜集到額令牌算法:

          令牌桶限流算法

          首先我們先回憶下令牌桶算法的原理:在令牌桶算法中,令牌生產(chǎn)算法以恒定速率不斷生成新的令牌放進(jìn)令牌桶中,當(dāng)數(shù)量達(dá)到令牌桶的上線時(shí),生成的新令牌會(huì)被丟棄掉。對(duì)客戶端請(qǐng)求來說,每次請(qǐng)求處理前,先要從令牌桶中獲取令牌,如果獲取到令牌,則進(jìn)出接口服務(wù)處理相關(guān)請(qǐng)求,否則請(qǐng)求被拒絕。

          在令牌桶限流算法中,最核心的點(diǎn)有以下幾個(gè):

          • 令牌的生成速率控制
          • 令牌的補(bǔ)充
          • 令牌的消耗
          • 令牌的獲取

          我測(cè)試了網(wǎng)上絕大多數(shù)算法實(shí)現(xiàn),最后只找到一種完全滿足需求的算法:

          public?class?TokenBucket5?{
          ????private?ArrayBlockingQueue?blockingQueue;
          ????private?int?limit;
          ????private?TimeUnit?unit;
          ????private?int?rate;
          ????private?ScheduledExecutorService?scheduledExecutorService?=?Executors.newScheduledThreadPool(1);

          ????public?TokenBucket5(int?capacity,?TimeUnit?unit,?int?rate)?{
          ????????//?存放令牌的隊(duì)列
          ????????this.blockingQueue?=?new?ArrayBlockingQueue<>(capacity);
          ????????//?令牌桶容量
          ????????this.capacity?=?capacity;
          ????????//?限流的時(shí)間單位
          ????????this.unit?=?unit;
          ????????//?限流的時(shí)間限制(速度),用于控制令牌生成速度
          ????????this.rate?=?rate;
          ????????init();
          ????????start();
          ????}

          ????//?初始化令牌桶
          ????private?void?init()?{
          ????????for?(int?i?=?0;?i?????????????blockingQueue.add(i);
          ????????}
          ????}

          ????//?創(chuàng)建令牌
          ????private?void?createToken()?{
          ????????blockingQueue.offer(1);
          ????}

          ????//?啟動(dòng)令牌創(chuàng)建定時(shí)線程池
          ????private?void?start()?{
          ????????scheduledExecutorService.scheduleAtFixedRate(this::createToken,?rate,?rate,?unit);
          ????}

          ????//?獲取令牌資源
          ????public?boolean?acquire()?{
          ????????return?blockingQueue.poll()?==?null???false?:?true;
          ????}

          ????//?釋放線程池資源
          ????public?void?release()?{
          ????????scheduledExecutorService.shutdown();
          ????}
          }

          在這個(gè)算法實(shí)現(xiàn)中,令牌的生成采用了定時(shí)線程池,生成的線程池被放進(jìn)固定尺寸的令牌隊(duì)列中,獲取令牌時(shí)令牌從隊(duì)列中刪除掉(當(dāng)隊(duì)列的count0時(shí),返回為null,所以如果poll方法不為空時(shí)表示仍然有令牌),生成令牌時(shí)會(huì)將令牌插入隊(duì)列。

          測(cè)試

          下面我們進(jìn)行一些簡單測(cè)試:

          public?static?void?main(String[]?args)?{
          ????TokenBucket5?tokenBucket5?=?new?TokenBucket5(5,?TimeUnit.MILLISECONDS,?100);
          ????try?{
          ????????for?(int?i?=?0;?i?100;?i++)?{
          ????????????boolean?acquire?=?tokenBucket5.acquire();
          ????????????System.out.printf("timestamp:%s,?hello,result:?%s\n",?System.currentTimeMillis(),?acquire);
          ????????????Thread.sleep(5L);
          ????????}
          ????}?catch?(InterruptedException?e)?{
          ????????e.printStackTrace();
          ????}?finally?{
          ????????tokenBucket5.release();
          ????}

          }

          運(yùn)行結(jié)果如下:

          當(dāng)我們的業(yè)務(wù)處理時(shí)間很短,而令牌生成很慢時(shí),絕大多數(shù)請(qǐng)求都獲取令牌失敗(每隔100ms生成一個(gè),業(yè)務(wù)只需要5ms),如果將業(yè)務(wù)處理時(shí)間增加或者將令牌生成時(shí)間減小,這時(shí)候就可以發(fā)現(xiàn),絕大多數(shù)的業(yè)務(wù)都會(huì)處理成功,偶爾會(huì)有個(gè)別獲取令牌失敗:

          至此,我們的限流目的也基本上達(dá)到了。

          總結(jié)

          關(guān)于令牌桶限流這塊沒有什么好總結(jié)的,但是在整個(gè)檢索算法的過程中,感觸倒是不少,特別是越發(fā)地意識(shí)到自己對(duì)多線程這塊地認(rèn)知真的是太淺薄了,所以后面會(huì)加強(qiáng)這塊地學(xué)習(xí)。好了,今天就先到在這里吧,各位小伙伴,晚安吧!

          - END -


          瀏覽 48
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  夜夜精品一区二区无码 | 成人免费电影伊人大香蕉 | 久久久久久三级电影 | 波多野结衣一区二区三区免费视频 | 欧美色逼图|