Redis限流

在电商开发过程中,我们很多地方需要做限流,有的是从Nginx上面做限流,有的是从代码层面限流等,这里我们就是从代码层面用Redis计数器做限流,这里我们用C#语言来编写,且用特性(过滤器,拦截器)的形式拦截限流,CSRedis来作为redis的客户端包。

1-新建一个.NET CORE的WebApi项目

其中默认的Webapi如

   [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };
 
        private readonly ILogger<WeatherForecastController> _logger;
 
        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {

            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {

                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }

2-引入CSRedisCore包

使用方法可以访问地址https://github.com/ctstone/csredis

  

3-安装启动Redis

4-新建一个特性(过滤器,拦截器),名字叫RateLimitingAttirbute

public class RateLimitingAttirbute : ActionFilterAttribute
    {
        private readonly int _count;
        public RateLimitingAttirbute(int count)
        {
            _count = count;//请求次数闲置
        }
 
        public override async void OnActionExecuting(ActionExecutingContext context)
        {
            var userID = 0;//当我们在每个用户维度做限流,比如要限制每个用户的每个接口请求多少次,我们需要从请求头中解析用户信息,如token,获取用户的Id
            var redisKey = "RedisConsts.RateLimiter";//Redis的Key
            var csredis = new CSRedisClient("localhost");//链接Redis地址,这里默认本地地址
            RedisHelper.Initialization(csredis);

           //限流的redis的key是“RedisConsts.RateLimiter”+接口地址
 var RateLimiterKey = string.Format(redisKey, $"{userID}{context.HttpContext.Request.Path.Value.Replace("/", ":")}");//获取接口地址
            if (RedisHelper.Exists(RateLimiterKey))
            {
                string redisResult =await RedisHelper.GetAsync(RateLimiterKey);
                if (int.Parse(redisResult) >= _count)//当一分钟内的请求次数大于设置的次数,则拦截
                {

                    context.Result = new JsonResult( "请求过于频繁!");
                }
                else
                    await RedisHelper.IncrByAsync(RateLimiterKey, 1);
            }
            else
            {

                //1分钟内限制count次请求
                await RedisHelper.SetAsync(RateLimiterKey, 1, new TimeSpan(0, 0, 60));

            }

        }

    }

5-在WebApi中设置该特性

我们既可以放在某个Controller维度,也可以放在方法(Action)维度,下面的案例是放在Controller维度,下面的参数3表示一分钟内接口只能请求3次。

[ApiController]
    [Route("[controller]")]
    [RateLimitingAttirbute(3)]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };
 
        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }

6-运行项目,请求接口

http://localhost:53439/weatherforecast,开始是可以返回正常结果,是一个集合的值,连续请求多次,当超过3次时,会返回“请求过于频繁”

更多分享请关注我的公众号

原文地址:https://www.cnblogs.com/wangoublog/p/15330415.html