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/89820414,https://www.cyhone.com/articles/usage-of-golang-rate/,https://github.com/chenyahui/AnnotatedCode/blob/master/go/x/time/rate/rate.go