在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
算法原理固定窗口算法又称计数器算法,是一种简单的限流算法。在单位时间内设定一个阈值和一个计数值,每收到一个请求则计数值加一,如果计数值超过阈值则触发限流,如果达不到则请求正常处理,进入下一个单位时间后,计数值清零,重新累计。 如上图所示,时间单位是1秒,阈值是3。
算法实现这里讲两种实现方法:进程内即内存固定窗口算法、基于Redis的固定窗口算法。 进程内即内存固定窗口算法使用字典,Key是限流目标,Value包括计数值和过期时间。处理请求时,首先从请求中提取限流目标,然后根据限流目标去字典中查找,如果不存在,则添加一个字典项,计数值是1,过期时间是当前时间+限流单位时间;如果存在,则检查是否过期,如果过期,则计数值归1,过期时间是当前时间+限流单位时间,如果未过期,则仅计数值加1。这里需要注意多线程问题,读写数据时需要加锁。 在C#语言中可以使用MemoryCache,它的缓存项有一个过期时间,不需要自己回收过期的项目。 进程内计数的方法最适合单实例处理的程序限流,多实例处理的情况下可能每个实例收到的请求数不均匀,不能保证限流效果。 基于Redis的固定窗口算法Redis作为KV存储,类似于字典,而且也自带过期时间。处理请求时,首先从请求中提取限流目标,然后根据限流目标去Redis中查找,如果不存在,则添加KV项,Value值是1,过期时间是当前时间+限流单位时间;如果存在,则Value值加1。 这些操作逻辑可以封装在一个Lua script中,因为Lua script在Redis中执行时也是原子操作,所以Redis的限流计数在分布式处理时天然就是准确的。 算法应用这里以限流组件 FireflySoft.RateLimit 为例,实现ASP.NET Core中的固定窗口限流。 1、安装Nuget包有多种安装方式,选择自己喜欢的就行了。 包管理器命令:
或者.NET命令:
或者项目文件直接添加:
2、使用中间件在Startup中使用中间件,演示代码如下(下边会有详细说明): public void ConfigureServices(IServiceCollection services) { ... app.AddRateLimit(new InProcessFixedWindowAlgorithm( new[] { new FixedWindowRule() { ExtractTarget = context => { // 提取限流目标 return (context as HttpContext).Request.Path.Value; }, CheckRuleMatching = context => { // 判断当前请求是否需要限流处理 return true; }, Name="fixed window limit rule", LimitNumber=30, // 限流阈值 StatWindow=TimeSpan.FromSeconds(1) // 限流单位时间 } }) ); ... } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { ... app.UseRateLimit(); ... } 如上需要先注册服务,然后使用中间件。
基本的使用就是上边例子中的这些了。 如果还是基于传统的.NET Framework,则需要在Application_Start中注册一个消息处理器RateLimitHandler,算法和规则部分都是共用的,具体可以看Github上的使用说明:https://github.com/bosima/FireflySoft.RateLimit#aspnet FireflySoft.RateLimit 是一个基于 .NET Standard 的限流类库,其内核简单轻巧,能够灵活应对各种需求的限流场景。
Github开源地址:https://github.com/bosima/FireflySoft.RateLimit 到此这篇关于ASP.NET Core使用固定窗口限流的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持极客世界。 |
请发表评论