问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

ASP.NET Core中使用令牌桶算法限流

发布网友 发布时间:2024-09-29 10:27

我来回答

1个回答

热心网友 时间:2024-11-23 12:27

在服务限流时一般会*某个时间周期内的请求数,简单点会采用固定窗口算法(也称计数器算法),这种算法实现相对简单,也很高效;但在实际的应用场景中请求并不是特别均匀,某些情况下会产生一些瞬时的突发流量,然后很快恢复正常,很多时候这并不会对系统产生破坏性的影响,但是固定窗口算法不能很好的处理这种情况。

比如某个数据查询接口限流每秒100次请求,绝大多数的时间里都不会超过这个数,但是偶尔某一秒钟会达到120次请求,接着很快又会恢复正常。此时如果采用固定窗口算法会触发限流,用户的正常访问会被干扰,体验上不太好;如果接口的调用方还有重试的逻辑,则在后续的时间窗口内系统可能收到更多的请求,然后更多的请求被限流,又产生更多的重试请求,循环往复让系统的负担愈加沉重,严重的话可能导致系统崩溃。

假设上文中120次的请求不会对系统稳定性带来实质性的影响,则可以在一定程度上允许这种瞬时的突发流量,从而为用户带来更好的使用体验,也可一定程度上避免因为限流重试导致系统负担进一步加重的问题。本文就介绍一种令牌桶的算法来应对这个情况。

算法原理

说了这么多,那么令牌桶算法怎么解决问题的呢?请看下图:

如上图所示,该算法的基本原理是:有一个令牌桶,容量是X,每Y单位时间会向桶中放入Z个令牌,如果桶中的令牌数超过X,则丢弃令牌;请求要想通过首先需要从令牌桶中获取一个令牌,获取不到令牌则拒绝请求。可以看出对于令牌桶算法X、Y、Z这几个数的设定特别重要,Z应该略大于绝大数时候的Y单位时间内的请求数,系统会长期处于这个状态,X可以是系统允许承载的瞬时最大请求数,系统不能长时间处于这个状态。

算法实现

这里讲两种实现方法:进程内即内存令牌桶算法、基于Redis的令牌桶算法。

进程内即内存令牌桶算法

这里在请求时计算投放数量,没有单独的投放处理,比固定窗口算法麻烦一些,但是仔细阅读,也很容易理解。

使用字典,Key是限流目标,Value包括当前令牌桶令牌数和上次令牌投放时间。初始状态下,认为每个限流目标的令牌桶是装满的,即令牌桶令牌数=令牌桶容量,不过仅在处理中发现限流目标的令牌桶不存在时才创建这个令牌桶。

请求进入后,根据限流目标在字典中查找:

如果找不到,则创建令牌桶,并设置令牌数为:令牌桶容量-本次请求消耗令牌数,设置上次令牌投放时间为:当前时间。

如果找到,则计算当前时间与上次令牌投放时间之间的间隔:

如果大于等于令牌投放时间间隔,则计算令牌数为:max(令牌桶令牌数+令牌投放数量,令牌桶容量)-本次请求消耗令牌数,上次令牌投放时间为:当前时间。

如果小于令牌投放时间间隔,则计算令牌数为:令牌桶令牌数-本次请求消耗令牌数。‘

如果计算出的令牌数小于0,则触发限流,否则更新到令牌桶中。

在C#语言中可以使用MemoryCache,它的缓存项有一个过期时间,可以自动回收一些很少使用或者不再使用的令牌桶,减少内存占用。

进程内算法最适合单实例处理的程序限流,多实例处理的情况下可能每个实例收到的请求数不均匀,不能保证限流效果。

基于Redis的令牌桶算法

Redis作为KV存储,类似于字典,而且也自带过期时间。处理请求时,首先从请求中提取限流目标,然后根据限流目标去Redis中查找,其处理规则和内存算法一样,只不过使用了两个Redis KV:

限流目标的令牌桶,Value是当前令牌数。

限流目标的上次令牌投放时间,Value是上次投放令牌的时间戳。

这些操作逻辑可以封装在一个Lua script中,因为Lua script在Redis中执行时也是原子操作,所以Redis的限流计数在分布式部署时天然就是准确的。

应用算法

这里以限流组件 FireflySoft.RateLimit 为例,实现ASP.NET Core中的令牌桶算法限流。

1、安装Nuget包

有多种安装方式,选择自己喜欢的就行了。

包管理器命令:

Install-PackageFireflySoft.RateLimit.AspNetCore

或者.NET命令:

dotnetaddpackageFireflySoft.RateLimit.AspNetCore

或者项目文件直接添加:

<ItemGroup><PackageReferenceInclude="FireflySoft.RateLimit.AspNetCore"Version="2.*"/></ItemGroup>2、使用中间件

在Startup中使用中间件,演示代码如下(下边会有详细说明):

publicvoidConfigureServices(IServiceCollectionservices){...app.AddRateLimit(newInProcessTokenBucketAlgorithm(new[]{newTokenBucketRule(30,10,TimeSpan.FromSeconds(1)){ExtractTarget=context=>{return(contextasHttpContext).Request.Path.Value;},CheckRuleMatching=context=>{returntrue;},Name="defaultlimitrule",}}));...}publicvoidConfigure(IApplicationBuilderapp,IWebHostEnvironmentenv){...app.UseRateLimit();...}

如上需要先注册服务,然后使用中间件。

注册服务的时候需要提供限流算法和对应的规则:

这里使用进程内令牌桶算法,对于分布式服务可以使用RedisTokenBucketAlgorithm,支持StackExchange.Redis。

桶的容量是30,每秒流入10个令牌。最大能够允许每秒40次请求,最少能够允许每秒10次请求,绝大部分情况下不应该超过每秒10次,可以偶尔超过10次/秒,极少数情况下达到40次/秒。

ExtractTarget用于提取限流目标,这里是每个不同的请求Path,可以根据需求从当前请求中提取关键数据,然后设定各种限流目标。如果有IO请求,这里还支持对应的异步方法ExtractTargetAsync。

CheckRuleMatching用于验证当前请求是否限流,传入的对象也是当前请求,方便提取关键数据进行验证。如果有IO请求,这里还支持对应的异步方法CheckRuleMatchingAsync。

默认被限流时会返回HttpStatusCode 429,可以在AddRateLimit时使用可选参数error自定义这个值,以及Http Header和Body中的内容。

基本的使用就是上边例子中的这些了。

如果还是基于传统的.NET Framework,则需要在Application_Start中注册一个消息处理器RateLimitHandler,算法和规则部分都是共用的,具体可以看Github上的使用说明:https://github.com/bosima/FireflySoft.RateLimit#aspnet

FireflySoft.RateLimit 是一个基于 .NET Standard 的限流类库,其内核简单轻巧,能够灵活应对各种需求的限流场景。

其主要特点包括:

多种限流算法:内置固定窗口、滑动窗口、漏桶、令牌桶四种算法,还可自定义扩展。

多种计数存储:目前支持内存、Redis两种存储方式。

分布式友好:通过Redis存储支持分布式程序统一计数。

限流目标灵活:可以从请求中提取各种数据用于设置限流目标。

支持限流惩罚:可以在客户端触发限流后锁定一段时间不允许其访问。

动态更改规则:支持程序运行时动态更改限流规则。

自定义错误:可以自定义触发限流后的错误码和错误消息。

普适性:原则上可以满足任何需要限流的场景。

Github开源地址:https://github.com/bosima/FireflySoft.RateLimit

收获更多架构知识,公众号:萤火架构。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
人大政协辅助岗是什么 政务辅助人员是干什么 政府辅助人员是什么 努比亚的海拔什么意思 北非努比亚现在怎么样了啊 相邻权的相关法律 梦见老公离世了什么预兆 梦见自己老公走掉 你出轨后 怎么操作才没被发现? 评评怎么造句 下颚两侧两个球状物体是什么 下颌下腺炎怎么治疗 net:: errno_ invalid_ packet什么意思? VB.NET 打包安装到目标机后为何没有了声音? ...体检一下,谁能告诉我主要是体检哪几项,我要检查心,肝,脾,肺,能否... 发现颈部肿块怎么办? 我是一个can疾人办理个体公shang营业执照需要多少钱 急急,,残疾人开小商店用办营业执照吗?用花钱吗?用交税吗? 盘古祖殿原神殿简介 禄贤梁公祠地址在哪里? word文档文字出格了怎么办word文档文字出格了怎么办 李广被称为"龙城飞将",打仗能力值得怀疑? 螺旋定律是什么 qq好友验证怎么收不到啊 为什么有人发信息加我好友我收不到? 我在外地孩子就医要再户口所在地办转院吗 ...农村合作医疗在异地就医需要提前征得户口所在地相关部门同意么,还 ... 外省户口可以在异地医保吗? xp3文件怎么打开运行啊? xp3电脑怎么打开 我右颌下腺内可探及一回声结节,大小1.9*1.8*1.4,边界清,我需要切掉吗... wps office如何设置默认打开方式? 江口碳汇是什么意思? 在女生多的大学超市里什么东西比较好卖 丢饭碗是什么意思? 有一个粤语歌的歌词人生终有死我有负累是什么歌 求一首粤语歌 歌词有人生总可知不透 毛峰和毛尖的区别,茶叶毛峰和毛尖有何区别(五个不同之处) 我在起点写文是新人,现代言情,现在写了四万字了,有空中网的编辑找我... ...是一个新人。虽然看的人有1000多人,可是收藏的人却少得可怜... ...还没在起点签约,求读者们看一下我的文章是不是有什么不足之处... 详解喝普洱茶的坏处 植物大战僵尸2未来世界第二十二关怎么过 WOW有公共冷却的技能如何设宏 每次放完第一个技能 第2个就不放了_百度... 贵阳哪家医院是可以治疗癫痫病的?癫痫病要如何控制治疗? 美国wowwee哇威mip智能机器人怎么样 wow智能视角在哪怎么关闭,是界面,镜头里面那个智能调节吗?我改了看... wowawesome是什么梗 电脑怎么录制游戏视频呢? 大家认为加油金顺好看吗?拜托各位大神