像AspNetCoreRateLimit这种轮子我前面有给大家介绍过,今天就不说了,我们来聊聊背后的原理,欢迎各位大佬指正!
Like some APi request interface websites we often see:

Take the seven-day interface for requesting in major foreign cities as an example. Non-VIP users can only use it 2000 times, and VIP users can request it up to 10000 times a day. When requesting this interface, they must register an account to obtain the appid and key.
Then we design a current-limiting interface to obtain weather based on this requirement.
the first step
Verify whether the login account exists. If it does not exist, we throw a non-existent error
[HttpPost("GetWeather")]
public IActionResult ApiLimit(WeatherInfor weatherInfor)
{
if (!_userService.IsValid(weatherInfor.Appid, weatherInfor.Appsecret))
{
throw new Exception("账号或者密码错误");
}
}
the second step
Determine whether the account is a Vip user. If it is a VIP user, there is no total number of calls, only a single-day limit. Like this single-day limit, data that is cleared every other day, we definitely use caching to process. We set the settings every day. Whether all requests are cached at 23:59:59:59, this is the absolute expiration time of the cache.
The specific business logic is like this. Since the user's appid is unique, we can treat it as the key value and the number of calls as the value value. If the cache does not exist, we add the cache. If the cache exists, we will get the number of calls. If it is greater than 2000, we will tell the caller that the number of calls has been used up. If not, we will get the number of calls from the cache and give it +1.
** Cache Class **
public class MemoryCacheHelper
{
public static MemoryCache _cache = new MemoryCache(new MemoryCacheOptions());
/// <summary>
/// 验证缓存项是否存在
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
public static bool Exists(string key)
{
if (key == null)
{
return false;
}
return _cache.TryGetValue(key, out _);
}
/// <summary>
/// 获取缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
public static object Get(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (!Exists(key))
throw new ArgumentNullException(nameof(key));
return _cache.Get(key);
}
/// <summary>
/// 添加缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">缓存Value</param>
/// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
/// <param name="expiressAbsoulte">绝对过期时长</param>
/// <returns></returns>
public static bool AddMemoryCache(string key, object value)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
DateTime time = Convert.ToDateTime(DateTime.Now.AddDays(1).ToString("D").ToString()).AddSeconds(-1);
_cache.Set(key, value, time);
return Exists(key);
}
}
** Business Logic **
public bool IsLimit(string appId)
{
if (MemoryCacheHelper.Exists(appId))
{
int value = int.Parse(MemoryCacheHelper.Get(appId).ToString());
if (value > 2000)
return false;
else
value = value + 1;
MemoryCacheHelper.AddMemoryCache(appId, value);
}
else
{
MemoryCacheHelper.AddMemoryCache(appId, 1);
}
return true;
}
last
Go to the weather interface and return the data
[HttpPost("GetWeather")]
public IActionResult ApiLimit(WeatherInfor weatherInfor)
{
if (!_userService.IsValid(weatherInfor.Appid, weatherInfor.Appsecret))
{
throw new Exception("账号或者密码错误");
}
bool isLimit = false;
if (_userService.IsVIP(weatherInfor.Appid))
{
isLimit= _sqlServices.IsLimit(weatherInfor.Appid);
}
else
{
isLimit = _memoryCacheServices.IsLimit(weatherInfor.Appid);
}
if (isLimit)
{
//查询天气接口 返回数据
}
else
{
throw new Exception("调用次数已用完");
}
return Ok("");
}
Finally, if you like my article, please pay attention and like it, hoping that the net ecosystem will get better and better!