分布式限流常用算法

常見(jiàn)的限流方法有計(jì)數(shù)器、漏斗算法、令牌桶算法,各自也有各自的優(yōu)缺點(diǎn)

一 計(jì)數(shù)器限流方法

計(jì)數(shù)器算法比較簡(jiǎn)單,即一段時(shí)間內(nèi)的調(diào)用次數(shù)是有上限的,當(dāng)大于最大請(qǐng)求次數(shù),則拒絕服務(wù)
計(jì)數(shù)器算法偽代碼:

public class CounterDemo {
    public long timeStamp = getNowTime();
    public int reqCount = 0;
    public final int limit = 100; // 時(shí)間窗口內(nèi)最大請(qǐng)求數(shù)
    public final long interval = 1000; // 時(shí)間窗口ms
    public boolean grant() {
        long now = getNowTime();
        if (now < timeStamp + interval) {
            // 在時(shí)間窗口內(nèi)
            reqCount++;
            // 判斷當(dāng)前時(shí)間窗口內(nèi)是否超過(guò)最大請(qǐng)求控制數(shù)
            return reqCount <= limit;
        } else {
            timeStamp = now;
            // 超時(shí)后重置
            reqCount = 1;
            return true;
        }
    }
}

優(yōu)點(diǎn):原理簡(jiǎn)單,利于實(shí)現(xiàn)
缺點(diǎn):

  1. 不能很好地防止瞬時(shí)流量,在01-02秒之間,請(qǐng)求假如都在1.1秒處進(jìn)來(lái),導(dǎo)致瞬時(shí)流量很大,所以使用計(jì)數(shù)器方法時(shí),要預(yù)估好服務(wù)的瞬時(shí)承載能力
  2. 不能避免抖動(dòng)問(wèn)題


    image.jpeg

    如上圖,假設(shè)1秒內(nèi)最大請(qǐng)求數(shù)為100,所以在1-2秒之間最多只能有100次,在02秒時(shí)請(qǐng)求次數(shù)會(huì)被重置為0,重新計(jì)算,這樣極端情況會(huì)在存在在1.5-2.5秒之間的請(qǐng)求總數(shù)是200

二 漏斗限流方法

漏斗算法思想是將所有請(qǐng)求先存到一個(gè)桶里。若此刻桶容量沒(méi)滿,表示當(dāng)前請(qǐng)求是可以訪問(wèn)資源。若滿了,則拒絕服務(wù)。同時(shí)桶會(huì)以固定速率取出桶里的請(qǐng)求來(lái)處理

具體實(shí)現(xiàn)方法可以將請(qǐng)求先暫存到一個(gè)隊(duì)列中,若隊(duì)列已滿,則拒絕該請(qǐng)求。同時(shí)有一個(gè)周期性定時(shí)任務(wù)來(lái)消費(fèi)隊(duì)列里的數(shù)據(jù)

從實(shí)現(xiàn)可以看出,不管請(qǐng)求有多少或者瞬時(shí)流量有多大,請(qǐng)求的處理是固定速率的,所以令牌桶油流量整形的功能,具體實(shí)現(xiàn)代碼可以參考:限流-令牌桶實(shí)現(xiàn)(go版本)

相對(duì)計(jì)數(shù)器方法,令牌桶能有效避免抖動(dòng)的問(wèn)題,但當(dāng)瞬時(shí)請(qǐng)求量很大時(shí),后續(xù)的請(qǐng)求很有可能由于得不到及時(shí)處理而超時(shí)

三 令牌桶方法

當(dāng)一個(gè)請(qǐng)求進(jìn)來(lái)時(shí),它要先獲取一個(gè)token,若獲取成功,則可以訪問(wèn),若不成功,則會(huì)拒絕服務(wù)。存放令牌的地方就是令牌桶,令牌桶中的令牌會(huì)以固定速率生成

具體的令牌桶偽代碼:

public class TokenBucketDemo {
    public long timeStamp = getNowTime();
    public int capacity; // 桶的容量
    public int rate; // 令牌放入速度
    public int tokens; // 當(dāng)前令牌數(shù)量
    public boolean grant() {
        long now = getNowTime();
        // 先添加令牌
        tokens = min(capacity, tokens + (now - timeStamp) * rate);
        timeStamp = now;
        if (tokens < 1) {
            // 若不到1個(gè)令牌,則拒絕
            return false;
        }else {
            // 還有令牌,領(lǐng)取令牌
            tokens -= 1;
            return true;
        }
    }
}

令牌桶能夠承載一定的瞬時(shí)流量,并且也有一些廣泛的應(yīng)用,如Guava中基于令牌桶算法實(shí)現(xiàn)的限流器,阿里出品的sentinel

參考:

1. https://www.cnblogs.com/xuwc/p/9123078.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容