Asp.NET Core 限流控制(AspNetCoreRateLimit)的实现
起因:
近期项目中,提供了一些调用频率较高的api接口,需要保障服务器的稳定运行;需要对提供的接口进行限流控制。避免因客户端频繁的请求导致服务器的压力。
一、AspNetCoreRateLimit介绍
AspNetCoreRateLimit是一个ASP.NETCore速率限制的解决方案,旨在控制客户端根据IP地址或客户端ID向WebAPI或MVC应用发出的请求的速率。AspNetCoreRateLimit包含一个IpRateLimitMiddleware和ClientRateLimitMiddleware,每个中间件可以根据不同的场景配置限制允许IP或客户端,自定义这些限制策略,也可以将限制策略应用在每个APIURL或具体的HTTPMethod上。
二、AspNetCoreRateLimit使用
由上面介绍可知AspNetCoreRateLimit支持了两种方式:基于客户端IP(IpRateLimitMiddleware)和客户端ID(ClientRateLimitMiddleware)速率限制 接下来就分别说明使用方式
添加Nuget包引用:
Install-PackageAspNetCoreRateLimit
基于客户端IP速率限制
1、修改Startup.cs中方法:
publicclassStartup { publicStartup(IConfigurationconfiguration) { Configuration=configuration; } publicIConfigurationConfiguration{get;}//Thismethodgetscalledbytheruntime.Usethismethodtoaddservicestothecontainer. publicvoidConfigureServices(IServiceCollectionservices) { //需要从加载配置文件appsettings.json services.AddOptions(); //需要存储速率限制计算器和ip规则 services.AddMemoryCache(); //从appsettings.json中加载常规配置,IpRateLimiting与配置文件中节点对应 services.Configure(Configuration.GetSection("IpRateLimiting")); //从appsettings.json中加载Ip规则 services.Configure (Configuration.GetSection("IpRateLimitPolicies")); //注入计数器和规则存储 services.AddSingleton (); services.AddSingleton (); services.AddControllers(); services.AddSingleton (); //配置(解析器、计数器密钥生成器) services.AddSingleton (); //OtherCode } //Thismethodgetscalledbytheruntime.UsethismethodtoconfiguretheHTTPrequestpipeline. publicvoidConfigure(IApplicationBuilderapp,IWebHostEnvironmentenv) { //OtherCode app.UseRouting(); app.UseAuthorization(); //启用客户端IP限制速率 app.UseIpRateLimiting(); app.UseEndpoints(endpoints=> { endpoints.MapControllers(); }); } }
2、在appsettings.json中添加通用配置项节点:(IpRateLimiting节点与Startup中取的节点对应)
"IpRateLimiting":{ //false,则全局将应用限制,并且仅应用具有作为端点的规则*。例如,如果您设置每秒5次调用的限制,则对任何端点的任何HTTP调用都将计入该限制 //true,则限制将应用于每个端点,如{HTTP_Verb}{PATH}。例如,如果您为*:/api/values客户端设置每秒5个呼叫的限制, "EnableEndpointRateLimiting":false, //false,拒绝的API调用不会添加到调用次数计数器上;如客户端每秒发出3个请求并且您设置了每秒一个调用的限制,则每分钟或每天计数器等其他限制将仅记录第一个调用,即成功的API调用。如果您希望被拒绝的API调用计入其他时间的显示(分钟,小时等)//,则必须设置StackBlockedRequests为true。 "StackBlockedRequests":false, //Kestrel服务器背后是一个反向代理,如果你的代理服务器使用不同的页眉然后提取客户端IPX-Real-IP使用此选项来设置 "RealIpHeader":"X-Real-IP", //取白名单的客户端ID。如果此标头中存在客户端ID并且与ClientWhitelist中指定的值匹配,则不应用速率限制。 "ClientIdHeader":"X-ClientId", //限制状态码 "HttpStatusCode":429, ////IP白名单:支持Ipv4和v6 //"IpWhitelist":["127.0.0.1","::1/10","192.168.0.0/24"], ////端点白名单 //"EndpointWhitelist":["get:/api/license","*:/api/status"], ////客户端白名单 //"ClientWhitelist":["dev-id-1","dev-id-2"], //通用规则 "GeneralRules":[ { //端点路径 "Endpoint":"*", //时间段,格式:{数字}{单位};可使用单位:s,m,h,d "Period":"1s", //限制 "Limit":2 },//15分钟只能调用100次 {"Endpoint":"*","Period":"15m","Limit":100},//12H只能调用1000 {"Endpoint":"*","Period":"12h","Limit":1000},//7天只能调用10000次 {"Endpoint":"*","Period":"7d","Limit":10000} ] }
配置节点已添加相应注释信息。
规则设置格式:
端点格式:{HTTP_Verb}:{PATH},您可以使用asterix符号来定位任何HTTP谓词。
期间格式:{INT}{PERIOD_TYPE},您可以使用以下期间类型之一:s,m,h,d。
限制格式:{LONG}
3、特点Ip限制规则设置,在appsettings.json中添加IP规则配置节点
"IpRateLimitPolicies":{ //ip规则 "IpRules":[ { //IP "Ip":"84.247.85.224", //规则内容 "Rules":[ //1s请求10次 {"Endpoint":"*","Period":"1s","Limit":10}, //15分钟请求200次 {"Endpoint":"*","Period":"15m","Limit":200} ] }, { //ip支持设置多个 "Ip":"192.168.3.22/25", "Rules":[ //1秒请求5次 {"Endpoint":"*","Period":"1s","Limit":5}, //15分钟请求150次 {"Endpoint":"*","Period":"15m","Limit":150}, //12小时请求500次 {"Endpoint":"*","Period":"12h","Limit":500} ] } ] }
基于客户端ID速率限制
1、修改Startup文件:
publicvoidConfigureServices(IServiceCollectionservices) { //需要从加载配置文件appsettings.json services.AddOptions(); //需要存储速率限制计算器和ip规则 services.AddMemoryCache(); //从appsettings.json中加载常规配置 services.Configure(Configuration.GetSection("IPRateLimiting")); //从appsettings.json中加载客户端规则 services.Configure (Configuration.GetSection("ClientRateLimitPolicies")); //注入计数器和规则存储 services.AddSingleton (); services.AddSingleton (); services.AddControllers(); //https://github.com/aspnet/Hosting/issues/793 //theIHttpContextAccessorserviceisnotregisteredbydefault. //注入计数器和规则存储 services.AddSingleton (); //配置(解析器、计数器密钥生成器) services.AddSingleton (); } publicvoidConfigure(IApplicationBuilderapp,IHostingEnvironmentenv) { //启用客户端限制 app.UseClientRateLimiting(); app.UseMvc(); }
2、通用配置采用IP限制相同配置,添加客户端限制配置:
//客户端限制设置 "ClientRateLimitPolicies":{ "ClientRules":[ { //客户端id "ClientId":"client-id-1", "Rules":[ {"Endpoint":"*","Period":"1s","Limit":10}, {"Endpoint":"*","Period":"15m","Limit":200} ] }, { "ClientId":"client-id-2", "Rules":[ {"Endpoint":"*","Period":"1s","Limit":5}, {"Endpoint":"*","Period":"15m","Limit":150}, {"Endpoint":"*","Period":"12h","Limit":500} ] } ] }
3、调用结果:
设置规则:1s只能调用一次:首次调用
调用第二次:自定义返回内容
三、其他
运行时更新速率限制
添加IpRateLimitController控制器:
//////IP限制控制器 /// [Route("api/[controller]")] [ApiController] publicclassIpRateLimitController:ControllerBase { privatereadonlyIpRateLimitOptions_options; privatereadonlyIIpPolicyStore_ipPolicyStore; ////// /// ////// publicIpRateLimitController(IOptions optionsAccessor,IIpPolicyStoreipPolicyStore) { _options=optionsAccessor.Value; _ipPolicyStore=ipPolicyStore; } /// ///获取限制规则 /// ///[HttpGet] publicasyncTask Get() { returnawait_ipPolicyStore.GetAsync(_options.IpPolicyPrefix); } /// /// /// [HttpPost] publicasyncTaskPost(IpRateLimitPolicyipRate) { varpol=await_ipPolicyStore.GetAsync(_options.IpPolicyPrefix); if(ipRate!=null) { pol.IpRules.Add(ipRate); await_ipPolicyStore.SetAsync(_options.IpPolicyPrefix,pol); } } }
分布式部署时,需要将速率限制计算器和ip规则存储到分布式缓存中如Redis
修改注入对象
//injectcounterandrulesdistributedcachestores services.AddSingleton(); services.AddSingleton ();
添加Nuget包 Microsoft.Extensions.Caching.StackExchangeRedis
在Startup中设置Redis连接
services.AddStackExchangeRedisCache(options=> { options.ConfigurationOptions=newConfigurationOptions { //silentlyretryinthebackgroundiftheRedisconnectionistemporarilydown AbortOnConnectFail=false }; options.Configuration="localhost:6379"; options.InstanceName="AspNetRateLimit"; });
限制时自定义相应结果:
//请求返回 "QuotaExceededResponse":{ "Content":"{{\"code\":429,\"msg\":\"Visittoofrequently,pleasetryagainlater\",\"data\":null}}", "ContentType":"application/json;utf-8", "StatusCode":429 },
调用时返回结果:
其他:
示例代码:https://github.com/cwsheng/WebAPIVersionDemo
到此这篇关于Asp.NETCore限流控制(AspNetCoreRateLimit)的实现的文章就介绍到这了,更多相关Asp.NETCore限流控制内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。