cpp服务器访问量限制设计有2种思路
思路一:
- 使用map容器,记录IP和count,同一个IP在限制时间内在次访问,count++;不在同一限制时间内,重新计数。
- 开启独立线程,每隔一个限制时间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();
}
思路二:
- 使用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 << " 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次达不到限制目的,如果要求没有精确到毫秒这两个方法是可行的。
版权声明:拷贝、转载请附上本文连接