高并發(fā)的場景下扮授,不能不說的限流算法

先舉個例子,說明為什么要做“限流”专肪。

旅游景點通常都會有最大的接待量刹勃,不可能無限制的放游客進入,比如故宮每天只賣八萬張票嚎尤,超過八萬的游客荔仁,無法買票進入,因為如果超過八萬人芽死,景點的工作人員可能就忙不過來乏梁,過于擁擠的景點也會影響游客的體驗和心情,并且還會有安全隱患关贵;

只賣 N 張票遇骑,這就是一種限流的手段。

軟件架構中的限流

軟件架構中的限流也是類似揖曾,也是當系統(tǒng)資源不夠的時候落萎,已經不足以應對大量的請求,為了保證服務還能夠正常運行炭剪,那么按照規(guī)則练链,系統(tǒng)會把多余的請求直接拒絕掉,以達到限流的效果奴拦;

對外限流:用戶過多媒鼓,或因為某個活動或熱點問題引發(fā)的訪問量的增加;惡意攻擊错妖,或被爬蟲抓取數據等等绿鸣。不知道大家注意過沒有,比如雙11暂氯,剛過12點有些顧客的網頁或APP會顯示下單失敗的提示潮模,有些就是被限流掉了。

對內限流:大部分公司株旷,系統(tǒng)和系統(tǒng)之間都會相互調用再登,假如 A 系統(tǒng) 被 X、Y晾剖、Z 三個系統(tǒng)調用锉矢,當 X 系統(tǒng)的訪問量徒增,導致 A 系統(tǒng)被調的掛掉了齿尽,那么會導致 Y沽损、Z 系統(tǒng)也無法正常使用(依賴于 A 系統(tǒng))。

計數器法

計數器法的原理就是限制單位時間內的處理請求數不超過閾值循头。

比如一個接口一分鐘可以處理 1000 次請求绵估,那么可以設置一個計數器,當有一次請求過來卡骂,計數器就加 1国裳,如果一分鐘以內計數器超過了 1000,那么后面再過來的請求就不再處理全跨;

但是這個方法的缺點也很明顯缝左,因為請求的訪問不一定是很平穩(wěn)的,如果 0:59 過來了 1000 個請求浓若,1:01 已經是下一個窗口渺杉,又過來了 1000 個請求,但實際上三秒內來了 2000 個請求挪钓,已經超過我們的限流上限了是越;


計數器法
public class CounterTest {
   public static void main(String[] args) {
       long timeStamp = System.currentTimeMillis();
       int timeCount = 1;
    
       int reqCount = 0; //單位時間內的請求數量
       int reqCountTotal = 0; //請求總數
       
       final int limit = 10; // 時間窗口內最大請求數
       final long interval = 1000; // 時間窗口ms
       
       for(;;){
        // 當前時間
        long now = System.currentTimeMillis();
        
        if (now < timeStamp + interval) {
         //在之間窗口內
         reqCount ++ ;
         //沒有超過單位時間的請求數量
         if(reqCount < limit){
          reqCountTotal ++ ;
          System.out.println(timeCount + " : " + reqCountTotal);
         }
        }else {
         //下一個時間窗口
         timeStamp = now;
         reqCount = 0 ;
         timeCount ++ ;
        }
     }
   }
}

滑動窗口算法

還拿上面的例子,一分鐘分 6 份碌上,每份 10 秒倚评;每過 10 秒鐘,我們的時間窗口就會往右滑動一格馏予,每個格子都有獨立的計數器蔓纠,我們每次都計算時間窗口內的數量,可以解決計數器法中的問題吗蚌,而且當滑動窗口的格子越多腿倚,那么限流的統(tǒng)計就會越精確。

具體可以參考下圖蚯妇,看圖比較清晰:


滑動窗口法

漏桶算法

這個算法也很簡單敷燎,就是我們有一個固定容量的桶,有水流進來箩言,也有水流出去硬贯,我們不需要控制流進來的速度,只需要控制流出去的速度陨收,如果水流進來的太快饭豹,桶滿了鸵赖,多余的水會溢出去,并不會影響水流出去的速度拄衰。


漏桶算法

令牌桶算法

還是有一個桶它褪,桶里面有 N 個令牌,所有的請求在處理之前都需要拿到一個可用的令牌才會被處理翘悉,如果桶里面沒有令牌的話茫打,則拒絕服務;令牌桶算法的原理是系統(tǒng)會以一個恒定的速度往桶里放入令牌妖混。

有人會把漏桶算法和令牌桶算法混淆老赤,而從某種意義上講,令牌桶算法確實是對漏桶算法的一種改進制市,兩者的不同之處在于:漏桶算法能夠強行限制數據的傳輸速率抬旺,而令牌桶算法能夠在限制數據的平均傳輸速率的同時還允許某種程度的突發(fā)傳輸;

也就是說祥楣,如果令牌桶中存在令牌嚷狞,則允許發(fā)送流量;而如果令牌桶中不存在令牌荣堰,則不允許發(fā)送流量床未;放入令牌的動作是持續(xù)執(zhí)行的,比如桶的大小為 100 振坚,當一直沒有請求的時候薇搁,桶內的令牌數量始終保持在 100 ,當下一秒有大量請求過來的時候渡八,可以瞬間將“攢下”的 100 個令牌處理掉啃洋,然后再按照恒定速度進行處理。

令牌桶算法

再安利一下 Google 開源的 guava 包屎鳍,使用 RateLimiter 我們可以很輕松的創(chuàng)建一個令牌桶算法的限流器宏娄。

import java.util.concurrent.Executors;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.RateLimiter;

public class RateLimiterTest {
    public static void main(String[] args) {
        testRateLimiter();
    }
    
    public static void testRateLimiter() {   
        ListeningExecutorService executorService = MoreExecutors
                .listeningDecorator(Executors.newFixedThreadPool(5));
        RateLimiter limiter = RateLimiter.create(4); // 每秒不超過4個任務被提交

        int num = 0 ;
        for (;;) {
            limiter.acquire(); // 請求RateLimiter, 超過permits會被阻塞
            num ++ ;
            executorService.submit(new Task("is "+ num));
        }
    }
}

class Task implements Runnable{
    String str;
    public Task(String str){
        this.str = str;
    }
    @Override
    public void run() {
        System.out.println("Task call execute.." + str);
    }

}

會點代碼的大叔 | 文【原創(chuàng)】


敬請關注會點代碼的大叔
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市逮壁,隨后出現的幾起案子孵坚,更是在濱河造成了極大的恐慌,老刑警劉巖窥淆,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件卖宠,死亡現場離奇詭異,居然都是意外死亡忧饭,警方通過查閱死者的電腦和手機扛伍,發(fā)現死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來词裤,“玉大人刺洒,你說我怎么就攤上這事鳖宾。” “怎么了逆航?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵鼎文,是天一觀的道長。 經常有香客問我纸泡,道長,這世上最難降的妖魔是什么赖瞒? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任女揭,我火速辦了婚禮,結果婚禮上栏饮,老公的妹妹穿的比我還像新娘吧兔。我一直安慰自己,他們只是感情好袍嬉,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布境蔼。 她就那樣靜靜地躺著,像睡著了一般伺通。 火紅的嫁衣襯著肌膚如雪箍土。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天罐监,我揣著相機與錄音吴藻,去河邊找鬼。 笑死弓柱,一個胖子當著我的面吹牛沟堡,可吹牛的內容都是我干的。 我是一名探鬼主播矢空,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼航罗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了屁药?” 一聲冷哼從身側響起粥血,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎酿箭,沒想到半個月后立莉,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡七问,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年蜓耻,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片械巡。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡刹淌,死狀恐怖饶氏,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情有勾,我是刑警寧澤疹启,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站蔼卡,受9級特大地震影響喊崖,放射性物質發(fā)生泄漏。R本人自食惡果不足惜雇逞,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一荤懂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧塘砸,春花似錦节仿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至女轿,卻和暖如春箭启,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蛉迹。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工册烈, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人婿禽。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓赏僧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親扭倾。 傳聞我的和親對象是個殘疾皇子淀零,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內容