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

更多分享請關注我的公眾號