《cpp服務器訪問量限制設計思路》——精確到秒級別

cpp服務器訪問量限制設計有2種思路

思路一:

  1. 使用map容器,記錄IP和count,同一個IP在限制時間內在次訪問,count++;不在同一限制時間內,重新計數。
  2. 開啓獨立線程,每隔一個限制時間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();
	}

思路二:

  1. 使用map容器(與上面不同,這裏key存ip,value存time和count),記錄IP和time、count,同一個IP在同time內在次訪問,count++;不在同一限制時間內,重新計數。
  2. 區別不需要開啓新線程維護過期數據;直接在一個限制函數內完成業務邏輯
  3. 對於精確到毫秒的限制仍然存在臨界點問題
    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;
}

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