漏斗限流法

C++漏斗限流法

我們可以看到,就像一個漏斗一樣,進來的水量就好像訪問流量一樣,而出去的水量就像是我們的系統處理請求一樣。當訪問流量過大時這個漏斗中就會積水,如果水太多了就會溢出。
一般來說,這個“漏斗”是用一個隊列來實現的,當請求過多時,隊列就會開始積壓請求,如果隊列滿了,就會開拒絕請求。很多系統都有這樣的設計,比如TCP。當請求的數量過多 時,就會有一個sync backlog的隊列來緩衝請求,或是TCP的滑動窗口也是用於流控的隊列。
// g++ bucket_limit.cpp -std=c++11
#include<iostream>
#include<sys/time.h>
#include<unordered_map>
#include<map>
#include <unistd.h>

using namespace std;

// 漏斗限流
class BucketLimit {
public:
    BucketLimit(int rate, int bucket):rate_(rate), bucket_(bucket), cur_bucket_(0), last_time_(now_micro_seconds() / kMicroSecondsPerSecond) {
    }
    void refresh() {
        int now = now_micro_seconds() / kMicroSecondsPerSecond; // 當前時間,單位爲s
        cout << "now:" << now << " last_time_:" << last_time_ << endl;
        int consumer = (now - last_time_) * rate_; // 距離上次請求,這段時間已經消費多少請求
        cur_bucket_ = max(0, cur_bucket_ - consumer); // 當前剩餘水桶中水量
        last_time_ = now;
        ++cur_bucket_; // 水量增加1
    }
    bool allow() {
        refresh();
        cout << "cur_bucket_:" << cur_bucket_ << " bucket_:" << bucket_ << endl;
        if(cur_bucket_ < bucket_) {
            return true;
        }
        return false;
    }
private:
    int rate_; // 單位:r/s,每秒多少個request,qps
    int bucket_; // 水桶容量,超過水桶容量請求會被拒絕
    int64_t last_time_; // 以秒爲單位,保存上一次請求的時間戳
    int cur_bucket_; // 當前水桶中存在的水量

    // 獲取當前時間,單位爲us
    int64_t now_micro_seconds() {
        struct timeval tv;
        gettimeofday(&tv, NULL);
        int64_t seconds = tv.tv_sec;
        return seconds * kMicroSecondsPerSecond + tv.tv_usec;
    }
    static const int kMicroSecondsPerSecond = 1000 * 1000;
};

int main() {
    //std::unordered_map<int, bool> request_allow;
    std::map<int, bool> request_allow;
    // 限流50r/s,bucket爲100r
    BucketLimit bucket_limit(50, 100);
    // for循環速度很快,這個for循環執行肯定是<1s
    for(int i = 0; i < 1000; ++i) {
        if(bucket_limit.allow()) {
            request_allow[i] = true;
        } else {
            request_allow[i] = false;
            sleep(0.01);
        }
    }
    for(auto ite : request_allow) {
        cout << "i = " << ite.first << " allow = " << ite.second << endl;
    }
    return 0;
}

限流參考書籍:
1.《億級流量網站架構核心技術 跟開濤學搭建高可用高併發系統》第4章:限流詳解
2.《極客時間-OpenResty從入門到實戰》42丨如何應對突發流量:漏桶和令牌桶的概念
3.《網易雲-Golang從入門到精通》https://github.com/NIGHTFIGHTING/koala/tree/master/ppt/14.%20%E9%99%90%E6%B5%81%E4%B8%AD
4.令牌桶go源碼分析:
https://zhuanlan.zhihu.com/p/90206074

5.《極客時間-左耳聽風》彈力設計篇之“限流設計”

6.令牌桶:https://zhuanlan.zhihu.com/p/89820414https://www.cyhone.com/articles/usage-of-golang-rate/https://github.com/chenyahui/AnnotatedCode/blob/master/go/x/time/rate/rate.go

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章