C# 關於API 限制呼叫次數方法
一般簡訊介面,或者付費的介面,需要做一定時間內呼叫次數的限制。
本文主要根據客戶端 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;
}
}
}
}