【调整】移除第三方AspNetCoreRateLimit限流组件,使用.net8自带的RateLimiter特性。

This commit is contained in:
jianweie code
2023-11-17 13:36:08 +08:00
parent 4425c53413
commit 9efb2e11a6
11 changed files with 203 additions and 262 deletions

View File

@@ -14,12 +14,14 @@ using Microsoft.Extensions.Logging;
using NLog.Web;
using System;
using System.Linq;
using System.Threading.RateLimiting;
using CoreCms.Net.Auth;
using CoreCms.Net.Core.AutoFac;
using CoreCms.Net.Core.Config;
using CoreCms.Net.Filter;
using CoreCms.Net.Mapping;
using CoreCms.Net.Middlewares;
using CoreCms.Net.Model.ViewModels.Options;
using CoreCms.Net.Swagger;
using CoreCms.Net.Utility;
using Microsoft.Extensions.DependencyInjection.Extensions;
@@ -27,6 +29,8 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Yitter.IdGenerator;
using LogLevel = NLog.LogLevel;
using Microsoft.AspNetCore.RateLimiting;
using Microsoft.Extensions.Configuration;
var builder = WebApplication.CreateBuilder(args);
@@ -61,9 +65,6 @@ builder.Services.Configure<CoreCms.Net.WeChat.Service.Options.WeChatOptions>(bui
builder.Services.AddHttpClient();
builder.Services.AddSingleton<CoreCms.Net.WeChat.Service.HttpClients.IWeChatApiHttpClientFactory, CoreCms.Net.WeChat.Service.HttpClients.WeChatApiHttpClientFactory>();
//启用客户端IP限制速率
builder.Services.AddIpPolicyRateLimitSetup(builder.Configuration);
//Swagger接口文档注入
builder.Services.AddAdminSwaggerSetup();
@@ -76,15 +77,6 @@ builder.Services.AddHttpContextSetup();
//服务配置中加入AutoFac控制器替换规则。
builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
//并发限制-使用队列策略模式
builder.Services.AddQueuePolicy(options =>
{
//最大并发请求数,超过之后,进行排队
options.MaxConcurrentRequests = AppSettingsConstVars.MiddlewareConcurrencyLimiterMaxConcurrentRequests;
//最大请求数,超过之后,返回503
options.RequestQueueLimit = AppSettingsConstVars.MiddlewareConcurrencyLimiterRequestQueueLimit;
});
//注册mvc注册razor引擎视图
builder.Services.AddMvc(options =>
{
@@ -109,6 +101,24 @@ builder.Services.AddMvc(options =>
p.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
});
//调用 AddRateLimiter 来将速率限制服务添加到服务集合
builder.Services.Configure<MyRateLimitOptions>(builder.Configuration.GetSection(MyRateLimitOptions.MyRateLimit));
var myOptions = new MyRateLimitOptions();
builder.Configuration.GetSection(MyRateLimitOptions.MyRateLimit).Bind(myOptions);
var fixedPolicy = "fixed";
builder.Services.AddRateLimiter(_ => _
.AddFixedWindowLimiter(policyName: fixedPolicy, options =>
{
options.PermitLimit = myOptions.PermitLimit;
//options.Window = TimeSpan.FromSeconds(myOptions.Window); //不走窗口限制了。直接走请求数限制。
options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
options.QueueLimit = myOptions.QueueLimit;
}));
// 雪花漂移算法
// 创建 IdGeneratorOptions 对象,请在构造函数中输入 WorkerId
var options = new IdGeneratorOptions(1);
@@ -160,10 +170,8 @@ app.UseForwardedHeaders(new ForwardedHeadersOptions
#region ===================================================================
// 获取用户访问真实ip
app.RealIpMiddleware();
// 启用并发限制中间件
app.UseConcurrencyLimiter();
// 开启Ip限流
app.UseIpLimitMiddle();
// 启用速率限制中间件
app.UseRateLimiter();
// 记录请求与返回数据 (注意开启权限,不然本地无法写入)
app.UseRequestResponseLog();
// 用户访问记录(必须放到外层,不然如果遇到异常,会报错,因为不能返回流)(注意开启权限,不然本地无法写入)

View File

@@ -61,74 +61,25 @@
//开启Ip限流
"IpRateLimit": {
"Enabled": false
},
"ConcurrencyLimiter": {
//最大并发请求数
"MaxConcurrentRequests": 100,
//最大请求数
"RequestQueueLimit": 100
}
},
//ip限流规则设
"IpRateLimiting": {
//如果EnableEndpointRateLimiting设置为false则限制将在全局范围内应用并且仅适用于端点的规则*。例如,如果您设置每秒 5 次调用的限制,则对任何端点的任何 HTTP 调用都将计入该限制。
//如果EnableEndpointRateLimiting设置为true则限制将适用于每个端点如{HTTP_Verb}{PATH}。例如,如果您为*:/api/values客户端设置每秒调用 5 次的限制则每秒可以调用GET /api/values5 次,但也可以调用 5 次PUT /api/values
"EnableEndpointRateLimiting": false,
//如果StackBlockedRequests设置为false则拒绝的呼叫不会添加到节流计数器。如果客户端每秒发出 3 个请求并且您设置了每秒一个呼叫的限制则其他限制例如每分钟或每天计数器将仅记录第一个呼叫即未被阻止的呼叫。如果您希望被拒绝的请求计入其他限制您必须设置StackBlockedRequests为true.
"StackBlockedRequests": false,
//用于在您的RealIpHeaderKestrel 服务器位于反向代理之后时提取客户端 IP如果您的代理使用不同的标头则X-Real-IP使用此选项进行设置
"RealIpHeader": "X-Real-IP",
//ClientIdHeader用于提取白名单的客户端 ID 。如果此标头中存在客户端 ID 并且与 ClientWhitelist 中指定的值匹配,则不应用速率限制
"ClientIdHeader": "X-ClientId",
//IP白名单:支持Ip v4和v6如 //"IpWhitelist": [ "127.0.0.1", "::1/10", "192.168.0.0/24" ],
"IpWhitelist": [],
//端点白名单
"EndpointWhitelist": [ "get:/api/license", "*:/api/status" ],
//客户端白名单
"ClientWhitelist": [ "dev-client-1", "dev-client-2" ],
"QuotaExceededResponse": {
"Content": "{{\"status\":429,\"msg\":\"访问过于频繁,请稍后重试\",\"success\":false}}",
"ContentType": "application/json",
"StatusCode": 429
},
//返回状态码
"HttpStatusCode": 429,
//通用规则
//api规则,结尾一定要带*
"GeneralRules": [
//{
// //端点路径
// "Endpoint": "*:/api/*",
// //时间段,格式:{数字}{单位}可使用单位s, m, h, d
// "Period": "1m",
// //限制数量
// "Limit": 60
//},
//1秒钟只能调用3次
{
"Endpoint": "*",
"Period": "1s",
"Limit": 30
},
//1分钟只能调用300次
{
"Endpoint": "*",
"Period": "1m",
"Limit": 1000
},
//12H只能调用10000
{
"Endpoint": "*",
"Period": "12h",
"Limit": 100000
},
//7天只能调用100000次
{
"Endpoint": "*",
"Period": "7d",
"Limit": 1000000
}
]
//UseRateLimiter限流中间件配
"MyRateLimitOptions": {
"MyRateLimit": {
//一个窗口中允许的最大允许计数器数。 在将这些选项传递给 的FixedWindowRateLimiter构造函数时必须设置为值 &gt; 0
"PermitLimit": 100,
//指定请求的时间范围。 必须设置为大于 Zero 将这些选项传递给 的构造函数 FixedWindowRateLimiter时的值。
"Window": 10,
//当 AutoReplenishment 设置为 true 时,内部计时器每 ReplenishmentPeriod 时间补充一次令牌数;当 false 设置为 TryReplenish 时,应用必须对限制器调用
"ReplenishmentPeriod": 2,
//排队的获取请求的最大累计允许计数。 将这些选项传递给 的FixedWindowRateLimiter构造函数时必须设置为值 &gt;= 0
"QueueLimit": 2,
"SegmentsPerWindow": 8,
"TokenLimit": 10,
"TokensPerPeriod": 4,
//是否自动补货
"AutoReplenishment": false
}
},
"Logging": {
"LogLevel": {