《cpp服务器访问量限制设计思路》——精确到秒级别

cpp服务器访问量限制设计有2种思路

思路一:

  1. 使用map容器,记录IP和count,同一个IP在限制时间内在次访问,count++;不在同一限制时间内,重新计数。
  2. 开启独立线程,每隔一个限制时间clear()一次。然后计数线程又重新计数(注意清零线程和计数线程要加锁)。
    3. 请仔细研究代码,详细思路在代码注释
    这个方法好处在于可以解耦,负责计数限制和负责维护过期计数分开。(但对于精确到毫秒的限制存在临界点问题。)

示例代码:

#define Max_count 10
map<string,int> IP_count;//全局

/*------------------------------------------------*/
//负责计数和限制的线程
std::unique_lock<std::mutex> _lock(mutex_count);
map<string,int> ::iterator it = IP_count.find(IP);
if (it != IP_count.end())//map容器存在此ip
{
	if (it->second < Max_count)//此ip的访问计数尚未超过限制
	{
		(it->second)++;
	}
	else//此ip的访问计数超过限制Max_count
	{
		return "order too much";
	}
}
else//map容器不存在此ip,即是新来的请求
{
	IP_count[IP] = 1;
}

/*------------------------------------------------*/
//负责清理map过期计数的线程
	//开启线程
	void start_thread()
	{
		std::thread t2(&thread_clear, this);
		t2.detach();
	}
	//线程函数(做业务)
	void thread_clear()
	{
		while (true)
		{
			sleep(Max_sleep);//每隔一个限制时间清理一次map容器的计数
			clear_user_count();
		}
	}
	void clear_user_count()
	{
		std::unique_lock<std::mutex> _lock(mutex_count);
		//将内存中的计数归零
		IP_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 << " 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;
}

对于精确到毫秒的限制存在临界点问题:

比如限制规则:1秒访问20次。
可以在当前0.9秒内访问19次,然后线程清理掉了;
在接着下一秒到1.99访问20次;所以理论上可以访问39次达不到限制目的,如果要求没有精确到毫秒这两个方法是可行的。

原创文章 6 获赞 13 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_44757097/article/details/106057866
今日推荐