一般短信接口,或者付费的接口,需要做一定时间内调用次数的限制。
本文主要根据客户端 ip 做区分调用次数,只考虑可能会有一级代理级别。
首先,我们根据以下两行代码获取客户端ip
string IpAddress = "";//获取真实IP
if ((HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null
&& HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != String.Empty))
{
IpAddress = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
}
else
{
IpAddress= HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}
然后根据得到的ip去调用以下函数进行校验
/// <summary>
/// 限制API接口调用次数
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static bool CheckCount(string key)
{
TimeSpan Const_RedisKeyExpiryHours = new TimeSpan(1, 0, 0, 0);//缓存周期
string con = "jituan:Robotapi:count";//一般前缀
using (var redisClient = waterRedisClient.GetWaterClientManager())//对象池获取一个Redis客户端
{
if (!string.IsNullOrEmpty((string)redisClient.Redis.GetDatabase().StringGet(con + key+"black")))
{
return false; //黑名单检查
}
var tempkey = con + DateTime.Now.Hour + "_"+ key ;
var reslut =redisClient.Redis.GetDatabase().StringGet(tempkey);
if (reslut.IsNull)
{
redisClient.Redis.GetDatabase().StringSet(tempkey, 1, Const_RedisKeyExpiryHours);
return true;
}
else
{
var count = Convert.ToInt32(reslut);
if (count<20)//20以内不干预,无需检查
{
redisClient.Redis.GetDatabase().StringIncrement(tempkey);
return true;
}
else
{
double survivalTime = redisClient.Redis.GetDatabase().KeyTimeToLive(tempkey).Value.TotalSeconds;//剩余存活时间
double dieTime = 24 * 60 * 60 - survivalTime;//过去时间秒数
double limitCount = 0.8;//每秒限制的次数
double LimitMax = dieTime * limitCount;
if (LimitMax< count)
{
redisClient.Redis.GetDatabase().StringSet(con + "_black"+ key ,1, Const_RedisKeyExpiryHours);
return false;
}
redisClient.Redis.GetDatabase().StringIncrement(tempkey);
return true;
}
}
}
}