1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        最近學(xué)到的限流知識(shí)

        共 2738字,需瀏覽 6分鐘

         ·

        2019-09-10 23:22

        前言

        只有光頭才能變強(qiáng)。

        文本已收錄至我的GitHub倉(cāng)庫,歡迎Star:https://github.com/ZhongFuCheng3y/3y

        之前在學(xué)習(xí)的時(shí)候也接觸不到高并發(fā)/大流量這種東西,所以限流當(dāng)然是沒接觸過的了。在看公司項(xiàng)目的時(shí)候,發(fā)現(xiàn)有用到限流(RateLimiter),順帶了解一波。

        一、限流基礎(chǔ)知識(shí)介紹

        為啥要限流,相信就不用我多說了。

        • 比如,我周末去飯店吃飯,但是人太多了,我只能去前臺(tái)拿個(gè)號(hào),等號(hào)碼到我的時(shí)候才能進(jìn)飯店吃飯。如果飯店沒有限流怎么辦?一到飯點(diǎn),人都往里沖,而飯店又處理不了這么多人流,很容易就出事故(飯店塞滿了人,無路可走。飯店的工作人員崩潰了,處理不過來)

        • 回到代碼世界上也是一樣的,服務(wù)器能處理的請(qǐng)求數(shù)有限,如果請(qǐng)求量特別大,我們需要做限流(要么就讓請(qǐng)求等待,要么就把請(qǐng)求給扔了)

        e393c9dc51799eaafd76874a82a34e88.webp限流

        在代碼世界上,限流有兩種比較常見的算法:

        • 令牌桶算法

        • 漏桶算法

        1.1 什么是漏桶算法

        比如,現(xiàn)在我有一個(gè)桶子,綠色那塊是我能裝水的容量,如果超過我能裝下的容量,再往桶子里邊倒水,就會(huì)溢出來(限流):

        3346e8fd4951610da6c90fd21607738a.webp桶子

        我們目前可以知道的是:

        • 桶子的容量是固定的(是圖上綠色那塊)

        • 超出了桶子的容量就會(huì)溢出(要么等待,要么直接丟棄)

        OK,現(xiàn)在我們?cè)谕白永锿趥€(gè)洞,讓水可以從洞子里邊流出來:

        7f66bf7b2bf4bd7e1b2c17857c9e79de.webp挖了個(gè)洞,水從洞口流出來

        桶子的洞口的大小是固定的,所以水從洞口流出來的速率也是固定的。

        所以總結(jié)下來算法所需的參數(shù)就兩個(gè):

        • 桶子的容量

        • 漏水的速率

        漏桶算法有兩種實(shí)現(xiàn):

        1. 不允許突發(fā)流量的情況:如果進(jìn)水的速率大于出水的速率,直接舍棄掉多余的水。比如,我的桶子容量能裝100L,但我的桶子出水速率是10L/s。此時(shí),如果現(xiàn)在有100L/s的水進(jìn)來,我只讓10L的水進(jìn)到桶子,其余的都限流。(限定了請(qǐng)求的速度

        2. 允許一定的突發(fā)流量情況:我的桶子能裝100L,如果現(xiàn)在我的桶子是空的,那么這100L的水都能瞬間進(jìn)我的桶子。我以10L/s的速率將這些水流出,如果還有100L的水進(jìn)來,只能限流了。

        經(jīng)過上面的分析我們就知道:

        漏桶算法可以平滑網(wǎng)絡(luò)上的突發(fā)流量(因?yàn)槁┧乃俾适枪潭ǖ?

        1.2 什么是令牌桶算法

        現(xiàn)在我有另外一個(gè)桶子,這個(gè)桶子不用來裝水,用來裝令牌:

        4ef6b7e7cf65c16c23ab9c55ef1fbf79.webp桶子裝著令牌

        令牌會(huì)一定的速率扔進(jìn)桶子里邊,比如我1秒扔10個(gè)令牌進(jìn)桶子:

        2011f0fb07f12a9cbb7de4ed69bcea29.webp以一定的速率扔令牌進(jìn)桶子

        桶子能裝令牌的個(gè)數(shù)有上限的,比如我的桶子最多只能裝1000個(gè)令牌。

        每個(gè)請(qǐng)求進(jìn)來,就會(huì)去桶子拿一個(gè)令牌

        • 比如這秒我有1001個(gè)請(qǐng)求,我就去桶子里邊拿1001個(gè)令牌,此時(shí)可能會(huì)出現(xiàn)兩種情況:

          • 桶子里邊沒有1001個(gè)令牌,只有1000個(gè),那沒拿到令牌的請(qǐng)求只能被阻塞了(等待)

          • 桶子里邊有1001個(gè)令牌,所有請(qǐng)求都可以執(zhí)行。

        07e667f2d3b9a6853ec93bb04c860ecd.webp

        令牌桶算法支持網(wǎng)絡(luò)上的突發(fā)流量

        漏桶和令牌桶的區(qū)別:從上面的例子估計(jì)大家也能看出來了,漏桶只能以固定的速率去處理請(qǐng)求,而令牌桶可以以桶子最大的令牌數(shù)去處理請(qǐng)求

        二、RateLimiter使用

        RateLimiter是Guava的一個(gè)限流組件,我這邊的系統(tǒng)就有用到這個(gè)限流組件,使用起來十分方便。

        引入pom依賴:

        <dependency>
        ????<groupId>com.google.guavagroupId>
        ????<artifactId>guavaartifactId>
        ????<version>20.0version>
        dependency>

        RateLimiter它是基于令牌桶算法的,API非常簡(jiǎn)單,看以下的Demo:

        public?static?void?main(String[]?args)?{
        ????????//線程池
        ????????ExecutorService?exec?=?Executors.newCachedThreadPool();
        ????????//速率是每秒只有3個(gè)許可
        ????????final?RateLimiter?rateLimiter?=?RateLimiter.create(3.0);

        ????????for?(int?i?=?0;?i?100;?i++)?{
        ????????????final?int?no?=?i;
        ????????????Runnable?runnable?=?new?Runnable()?{
        ????????????????@Override
        ????????????????public?void?run()?{
        ????????????????????try?{
        ????????????????????????//獲取許可
        ????????????????????????rateLimiter.acquire();
        ????????????????????????System.out.println("Accessing:?"?+?no?+?",time:"
        ????????????????????????????????+?new?SimpleDateFormat("yy-MM-dd?HH:mm:ss").format(new?Date()));

        ????????????????????}?catch?(Exception?e)?{
        ????????????????????????e.printStackTrace();
        ????????????????????}

        ????????????????}
        ????????????};
        ????????????//執(zhí)行線程
        ????????????exec.execute(runnable);
        ????????}
        ????????//退出線程池
        ????????exec.shutdown();
        ????}

        我們可以從結(jié)果看出,每秒只能執(zhí)行三個(gè):

        c31de3986f911fc0d167aee737ac4dc9.webp每秒執(zhí)行三個(gè)

        三、分布式限流

        RateLimiter是一個(gè)單機(jī)的限流組件,如果是分布式應(yīng)用的話,該怎么做?

        可以使用Redis+Lua的方式來實(shí)現(xiàn),大致的lua腳本代碼如下:

        local?key?=?"rate.limit:"?..?KEYS[1]?--限流KEY
        local?limit?=?tonumber(ARGV[1])????????--限流大小
        local?current?=?tonumber(redis.call('get',?key)?or?"0")
        if?current?+?1?>?limit?then?--如果超出限流大小
        ??return?0
        else??--請(qǐng)求數(shù)+1,并設(shè)置1秒過期
        ??redis.call("INCRBY",?key,"1")
        ???redis.call("expire",?key,"1")
        ???return?current?+?1
        end

        Java代碼如下:

        public?static?boolean?accquire()?throws?IOException,?URISyntaxException?{
        ????Jedis?jedis?=?new?Jedis("127.0.0.1");
        ????File?luaFile?=?new?File(RedisLimitRateWithLUA.class.getResource("/").toURI().getPath()?+?"limit.lua");
        ????String?luaScript?=?FileUtils.readFileToString(luaFile);

        ????String?key?=?"ip:"?+?System.currentTimeMillis()/1000;?//?當(dāng)前秒
        ????String?limit?=?"5";?//?最大限制
        ????List?keys?=?new?ArrayList();
        ????keys.add(key);
        ????List?args?=?new?ArrayList();
        ????args.add(limit);
        ????Long?result?=?(Long)(jedis.eval(luaScript,?keys,?args));?//?執(zhí)行l(wèi)ua腳本,傳入?yún)?shù)
        ????return?result?==?1;
        }

        解釋:

        • Java代碼傳入key和最大的限制limit參數(shù)進(jìn)lua腳本

        • 執(zhí)行l(wèi)ua腳本(lua腳本判斷當(dāng)前key是否超過了最大限制limit)

          • 如果超過,則返回0(限流)

          • 如果沒超過,返回1(程序繼續(xù)執(zhí)行)

        參考來源:

        • https://segmentfault.com/a/1190000016552464

        更多資料參考:

        • https://segmentfault.com/a/1190000016042927

        • http://wuwenliang.net/2018/10/27/%E8%87%AA%E5%B7%B1%E5%86%99%E5%88%86%E5%B8%83%E5%BC%8F%E9%99%90%E6%B5%81%E7%BB%84%E4%BB%B6-%E5%9F%BA%E4%BA%8ERedis%E7%9A%84RateLimter/

        公眾號(hào)文章導(dǎo)航兩年嘔心瀝血的文章!


        200多篇原創(chuàng)技術(shù)文章海量視頻資源精美腦圖面試題

        長(zhǎng)按掃碼可關(guān)注獲取?

        在看和分享對(duì)我非常重要!054ea6bbc42153a59db902cf4bfacc7c.webp

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

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            北条麻妃一区二区三区在线播放 | 腿快张开(双肉合集) | 日本亲与子乱人妻hd | 高清无码三级 | a免费视频在线观看 | 18片毛片60分钟免费 | 欧美13一16娇小xxxx | 中国黄色网址 | 小黄片免费在线播放 | 美女露出让男生揉的电影 |