cpp服務器訪問量限制設計有2種思路
思路一:
- 使用map容器,記錄IP和count,同一個IP在限制時間內在次訪問,count++;不在同一限制時間內,重新計數。
- 開啓獨立線程,每隔一個限制時間clear()一次。然後計數線程又重新計數(注意清零線程和計數線程要加鎖)。
3. 請仔細研究代碼,詳細思路在代碼註釋
這個方法好處在於可以解耦,負責計數限制和負責維護過期計數分開。(但對於精確到毫秒的限制存在臨界點問題。)
比如限制規則:10毫秒訪問20次。
可以在當前10毫秒內訪問19次,然後線程清理掉了;
在接着訪問20次;所以理論上可以訪問39次達不到限制目的
示例代碼:
#define Max_count 10
map<string,int> user_count;//全局
/*------------------------------------------------*/
//負責計數和限制的線程
std::unique_lock<std::mutex> _lock(mutex_count);
map<string,int> ::iterator it = user_count.find(IP);
if (it != user_count.end())//map容器存在此ip
{
if (it->second < Max_count)//此ip的訪問計數尚未超過限制
{
(it->second)++;
}
else//此ip的訪問計數超過限制Max_count
{
return "order too frequently";
}
}
else//map容器不存在此ip,即是新來的請求
{
user_count[IP] = 1;
}
/*------------------------------------------------*/
//負責清理map過期計數的線程
//開啓線程
void start_thread()
{
std::thread t2(&CallProcessor::thread_clear, this);
t2.detach();
}
//線程函數(做業務)
void CallProcessor::thread_clear()
{
while (true)
{
sleep(Max_sleep);//每隔一個限制時間清理一次map容器的計數
clear_user_count();
}
}
void CallProcessor::clear_user_count()
{
std::unique_lock<std::mutex> _lock(mutex_count);
//將內存中的計數歸零
user_count.clear();
}
思路二:
- 使用map容器(與上面不同,這裏key存ip,value存time和count),記錄IP和time、count,同一個IP在同time內在次訪問,count++;不在同一限制時間內,重新計數。
- 區別不需要開啓新線程維護過期數據;直接在一個限制函數內完成業務邏輯
- 對於精確到毫秒的限制仍然存在臨界點問題
4. 請仔細研究代碼,詳細思路在代碼註釋
示例代碼:
//#define Max_count 10
struct My_count
{
int count = 0;
long Time = 0;
};
map<string, My_count> user_count;
//流控函數
bool test_cout(const int& Max_count, const string& IP)
{
long Curtime = time(NULL);
std::unique_lock<std::mutex> _lock(mutex);
map<string, My_count>::iterator it = user_count.find(IP);
if (it != user_count.end())//map容器存在此ip
{
if (Curtime > it->second.Time)//當前時間超過上一秒重新計數
{
it->second.count = 1;
it->second.Time = Curtime;
LOG << "IP:" << it->first << " overwrite count:" << it->second.count << endl;
}
else//還在當前一秒內判斷speed
{
if (it->second.count < Max_count)//小於限制數
{
++(it->second.count);
LOG << "IP: " << it->first << " second count:" << it->second.count << endl;
}
else//超過限定
{
return true;
}
}
}
else//map容器不存在此ip,即是新來的請求
{
user_count[IP].count = 1;
user_count[IP].Time = Curtime;
LOG << "IP: " << IP << " first count:" << user_count[IP].count << endl;
}
return false;
}