Asp.NET Core 限流控制-AspNetCoreRateLimit
起因:
近期项目中,提供了一些调用频率较高的api接口,需要保障服务器的稳定运行;需要对提供的接口进行限流控制。避免因客户端频繁的请求导致服务器的压力。
一、AspNetCoreRateLimit 介绍
AspNetCoreRateLimit是一个ASP.NET Core速率限制的解决方案,旨在控制客户端根据IP地址或客户端ID向Web API或MVC应用发出的请求的速率。AspNetCoreRateLimit包含一个IpRateLimitMiddleware和ClientRateLimitMiddleware,每个中间件可以根据不同的场景配置限制允许IP或客户端,自定义这些限制策略,也可以将限制策略应用在每个API URL或具体的HTTP Method上。
二、AspNetCoreRateLimit使用
由上面介绍可知AspNetCoreRateLimit支持了两种方式:基于客户端IP(IpRateLimitMiddleware)和客户端ID(ClientRateLimitMiddleware)速率限制 接下来就分别说明使用方式
添加Nuget包引用:
Install-Package AspNetCoreRateLimit
- 基于客户端IP速率限制
1、修改Startup.cs中方法:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
} public IConfiguration Configuration { get; }// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//需要从加载配置文件appsettings.json
services.AddOptions();
//需要存储速率限制计算器和ip规则
services.AddMemoryCache(); //从appsettings.json中加载常规配置,IpRateLimiting与配置文件中节点对应
services.Configure<IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting")); //从appsettings.json中加载Ip规则
services.Configure<IpRateLimitPolicies>(Configuration.GetSection("IpRateLimitPolicies")); //注入计数器和规则存储
services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();
services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>(); services.AddControllers(); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
//配置(解析器、计数器密钥生成器)
services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>(); //Other Code
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//Other Code 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 服务器背后是一个反向代理,如果你的代理服务器使用不同的页眉然后提取客户端IP X-Real-IP使用此选项来设置
"RealIpHeader": "X-Real-IP",
//取白名单的客户端ID。如果此标头中存在客户端ID并且与ClientWhitelist中指定的值匹配,则不应用速率限制。
"ClientIdHeader": "X-ClientId",
//限制状态码
"HttpStatusCode": 429,
////IP白名单:支持Ip v4和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文件:
public void ConfigureServices(IServiceCollection services)
{
//需要从加载配置文件appsettings.json
services.AddOptions(); //需要存储速率限制计算器和ip规则
services.AddMemoryCache(); //从appsettings.json中加载常规配置
services.Configure<ClientRateLimitOptions>(Configuration.GetSection("IPRateLimiting")); //从appsettings.json中加载客户端规则
services.Configure<ClientRateLimitPolicies>(Configuration.GetSection("ClientRateLimitPolicies")); //注入计数器和规则存储
services.AddSingleton<IClientPolicyStore, MemoryCacheClientPolicyStore>();
services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>(); services.AddControllers(); // https://github.com/aspnet/Hosting/issues/793
// the IHttpContextAccessor service is not registered by default.
//注入计数器和规则存储
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); //配置(解析器、计数器密钥生成器)
services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
} public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//启用客户端限制
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控制器:
/// <summary>
/// IP限制控制器
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class IpRateLimitController : ControllerBase
{ private readonly IpRateLimitOptions _options;
private readonly IIpPolicyStore _ipPolicyStore; /// <summary>
///
/// </summary>
/// <param name="optionsAccessor"></param>
/// <param name="ipPolicyStore"></param>
public IpRateLimitController(IOptions<IpRateLimitOptions> optionsAccessor, IIpPolicyStore ipPolicyStore)
{
_options = optionsAccessor.Value;
_ipPolicyStore = ipPolicyStore;
} /// <summary>
/// 获取限制规则
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<IpRateLimitPolicies> Get()
{
return await _ipPolicyStore.GetAsync(_options.IpPolicyPrefix);
} /// <summary>
///
/// </summary>
[HttpPost]
public async Task Post(IpRateLimitPolicy ipRate)
{
var pol = await _ipPolicyStore.GetAsync(_options.IpPolicyPrefix);
if (ipRate != null)
{
pol.IpRules.Add(ipRate);
await _ipPolicyStore.SetAsync(_options.IpPolicyPrefix, pol);
}
}
}
- 分布式部署时,需要将速率限制计算器和ip规则存储到分布式缓存中如Redis
- 修改注入对象
// inject counter and rules distributed cache stores
services.AddSingleton<IClientPolicyStore, DistributedCacheClientPolicyStore>();
services.AddSingleton<IRateLimitCounterStore,DistributedCacheRateLimitCounterStore>();
- 添加Nuget包 Microsoft.Extensions.Caching.StackExchangeRedis
- 在Startup中设置Redis连接
services.AddStackExchangeRedisCache(options =>
{
options.ConfigurationOptions = new ConfigurationOptions
{
//silently retry in the background if the Redis connection is temporarily down
AbortOnConnectFail = false
};
options.Configuration = "localhost:6379";
options.InstanceName = "AspNetRateLimit";
});
- 限制时自定义相应结果:
//请求返回
"QuotaExceededResponse": {
"Content": "{{\"code\":429,\"msg\":\"Visit too frequently, please try again later\",\"data\":null}}",
"ContentType": "application/json;utf-8",
"StatusCode": 429
},
调用时返回结果:

其他:
示例代码:https://github.com/cwsheng/WebAPIVersionDemo
Asp.NET Core 限流控制-AspNetCoreRateLimit的更多相关文章
- ASP.NET Core WebApi AspNetCoreRateLimit 限流中间件学习
AspNetCoreRateLimit介绍: AspNetCoreRateLimit是ASP.NET核心速率限制框架,能够对WebApi,Mvc中控制限流,AspNetCoreRateLimit包包含 ...
- ASP.NET Core中如何对不同类型的用户进行区别限流
老板提出了一个新需求,从某某天起,免费用户每天只能查询100次,收费用户100W次. 这是一个限流问题,聪明的你也一定想到了如何去做:记录用户每一天的查询次数,然后根据当前用户的类型使用不同的数字做比 ...
- ASP.NET Core中使用令牌桶限流
在限流时一般会限制每秒或每分钟的请求数,简单点一般会采用计数器算法,这种算法实现相对简单,也很高效,但是无法应对瞬时的突发流量. 比如限流每秒100次请求,绝大多数的时间里都不会超过这个数,但是偶尔某 ...
- ASP.NET Core中使用固定窗口限流
算法原理 固定窗口算法又称计数器算法,是一种简单的限流算法.在单位时间内设定一个阈值和一个计数值,每收到一个请求则计数值加一,如果计数值超过阈值则触发限流,如果达不到则请求正常处理,进入下一个单位时间 ...
- ASP.NET Core中使用滑动窗口限流
滑动窗口算法用于应对请求在时间周期中分布不均匀的情况,能够更精确的应对流量变化,比较著名的应用场景就是TCP协议的流量控制,不过今天要说的是服务限流场景中的应用. 算法原理 这里假设业务需要每秒钟限流 ...
- ASP.NET Core中使用漏桶算法限流
漏桶算法是限流的四大主流算法之一,其应用场景各种资料中介绍的不多,一般都是说应用在网络流量控制中.这里举两个例子: 1.目前家庭上网都会限制一个固定的带宽,比如100M.200M等,一栋楼有很多的用户 ...
- ASP.NET Core中的依赖注入(4): 构造函数的选择与服务生命周期管理
ServiceProvider最终提供的服务实例都是根据对应的ServiceDescriptor创建的,对于一个具体的ServiceDescriptor对象来说,如果它的ImplementationI ...
- ASP.NET Core 中文文档 第四章 MVC(3.6.1 )Tag Helpers 介绍
原文:Introduction to Tag Helpers 作者:Rick Anderson 翻译:刘浩杨 校对:高嵩(Jack) 什么是 Tag Helpers? Tag Helpers 提供了什 ...
- ASP.NET Core 源码学习之 Logging[1]:Introduction
在ASP.NET 4.X中,我们通常使用 log4net, NLog 等来记录日志,但是当我们引用的一些第三方类库使用不同的日志框架时,就比较混乱了.而在 ASP.Net Core 中内置了日志系统, ...
随机推荐
- struts 返回字符串
方法一: HttpServletResponse response = ServletActionContext.getResponse(); response.getWriter().print(& ...
- B - How Many Tables (多少桌)
题目大致意思: 有n个人在一起吃饭,有些人互相认识.认识的人想坐在一起,不想跟陌生人坐.例如A认识B,B认识C,那么A.B.C会坐在一张桌子上. 给出认识的人,问需要多少张桌子 Today is Ig ...
- 2020牛客暑期多校训练营(第五场)B - Graph (异或 最小生成树 分治 Trie)
B - Graph 题目链接 每次操作不会改变两点之间的路径异或和 以 1 号点为起点,算出任意一点到 1 号点的异或值 dis[i](把该值当做 i 号点权值), 那么任意两点的异或值为 \(dis ...
- codeforces632D. Longest Subsequence (最小公倍数)
You are given array a with n elements and the number m. Consider some subsequence of a and the value ...
- python对csv文件读写的两种方式 和 读写文件编码问题处理
''' 如果文件读取数据出错,可以考虑加一个encoding属性,取值可以是:utf-8,gbk,gb18030 或者加一个属性error,取值为ignore,例如 open(path, encodi ...
- Java 窗口 绘制图形 #2
写在前面: 高考结束咧,爽到啊,好耶 完善了Java 窗口 绘制图形 #1里面的程序 加入了缩放平移功能,给代码加了注释 1 package my_package; 2 3 import java.a ...
- 用数组模拟STL中的srack(栈)和queue(队列)
我们在理解stack和queue的基础上可以用数组来代替这两个容器,因为STL中的stack和queue有可能会导致程序运行起来非常的慢,爆TLE,所以我们使用数组来模拟他们,不仅可以更快,还可以让代 ...
- hdu5459 Jesus Is Here
Problem Description I've sent Fang Fang around 201314 text messages in almost 5 years. Why can't she ...
- Java进阶专题(二十五) 分布式锁原理与实现
前言 现如今很多系统都会基于分布式或微服务思想完成对系统的架构设计.那么在这一个系统中,就会存在若干个微服务,而且服务间也会产生相互通信调用.那么既然产生了服务调用,就必然会存在服务调用延迟或失败 ...
- oranges-给mini os 添加内存管理,进程多级反馈队列,进程内存完整性度量
参考: 内存管理: https://www.jianshu.com/p/49cbaccd38c5 crc校验 https://www.cnblogs.com/zzdbullet/p/9580502.h ...