漏斗限流法

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

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