数据库
首页 > 数据库> > Redis限流

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次时,会返回“请求过于频繁”

 

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

 

标签:Redis,rng,Summaries,限流,new,logger,public
来源: https://www.cnblogs.com/wangoublog/p/15330415.html