在電商開發過程中,我們很多地方需要做限流,有的是從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次時,會返回“請求過於頻繁”
更多分享請關注我的公眾號