How to limit the number of interface requests in. NET Core

How to limit the number of interface requests in. NET Core

I have introduced wheels like AspNetCoreRateLimit to you before, but I won't talk about it today. Let's talk about the principles behind it.

最后更新 7/8/2022 6:54 AM
黑哥聊dotNet
预计阅读 4 分钟
分类
ASP.NET Core
标签
.NET C# ASP.NET Core

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!

Keep Exploring

延伸阅读

更多文章
同分类 / 同标签 6/22/2022

Localization of ASP.NET Core WebAPI (single resource file)

Microsoft's default method is that one class corresponds to multiple resource files, which is quite troublesome to use. This article introduces the use of single resource files, that is, all classes of the entire project correspond to a set of multi-language resource files.

继续阅读