更多分享请关注我的公众号
在电商开发过程中,我们很多地方需要做限流,有的是从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次时,会返回“请求过于频繁”
更多分享请关注我的公众号