前言
同事问我asp.netcore的ratelimiting是怎么使用的,我回答说很简单的,你只要按照如下步骤来:
- 在ratelimiteroptions上注册policy,记住policy对应的policyname
- 在web应用添加useratelimiter()中间件
- 在api对应的action上标注[enableratelimiting(policyname)]
半小时后,同事说要对我告知他的ratelimiter功能差评,因为他得写几十种policy工作量很大,就连policyname的取名都让他头大。
让ratelimiting更简单
我在基于yarp的网关上做过ratelimiting,将每个服务的所有endpoint描述导出放到网关做网关的子级路由,然后基于endpoint做可配置化的限流,代码实现上很复杂但使用灵活度非常可观。
但今天我们的问题范围是在单体webapplication中,如何减少我同事的限流工作量。
限流器attribute化
假如我们造了如下的attribute:
- [ratelimiter.concurrency(permitlimit: 10)]
- [ratelimiter.fixedwindow(permitlimit: 10, windowseconds: 60)]
- [ratelimiter.slidingwindow(permitlimit: 10, windowseconds: 60, segmentsperwindow: 5)]
让我的同事在action上标记其中一个attribute,他的开发时间短、代码可读性高,免去了他手写policy实现的巨量代码。
限流单元来源attribute化
同事说他的众多接口中,需要整体限流的很少,几乎都是需要颗粒度更细的限流:
- 登录接口,需要对请求体的json对象的username值做限流单元
- 找回密码接口,需要对请求路由里的username值做限流单元
- 其它已经做了用户身份认证的接口,需要用userid值做限流单元
- xx特殊接口,需要用请求者ip值做限流单元
- yy接口需要从form中取出yy值做限流单元
- zz接口需要从header中取出zz值做限流单元
- 想自定义从httpcontext里获取限流单元
于是我们又造了一些attribute,来处理上面的需求
- [ratelimiterunit.frombody(unitname: "$.username")]
- [ratelimiterunit.fromroute(unitname: "username")]
- [ratelimiterunit.fromuser(unitname: claimtypes.nameidentifier)]
- [ratelimiterunit.fromremoteipaddress]
- [ratelimiterunit.fromform(unitname: "yy")]
- [ratelimiterunit.fromheader(unitname: "zz")]
再提供一个iratelimiterunitmetadata接口,让他实现自定义逻辑
public class yourratelimiterunitattribute : attribute, iratelimiterunitmetadata { public valuetask<string?> getunitasync(httpcontext context) { throw new notimplementedexception(); } }
让ratelimiting能运行
上面提到的那些attribute,目前只存在于我们理想中,我们需要把它变成实际。
我们需要实现实现一个policy,在policy里获取当前请求的endpoint,从endpoint的metadata里提取出我们上面定义的attribute,根据attribute的描述生成ratelimitpartition。
把这个唯一的policy注册到ratelimiteroptions中,再把它的policyname使用enableratelimitingattribute添加到endpoint的metadata中。
最后,使用标准的asp.netcore的useratelimiter()中间件,就能把我们的限流器运行起来了。
最后
此项目是开源的,不管你在工作中有没有用到,但里面有意思的想法你可以来一起品。
到此这篇关于在asp.netcore中使用attribute来描述限流的文章就介绍到这了,更多相关asp.netcore attribute限流内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论