mirror of
http://git.coreshop.cn/jianweie/coreshoppro.git
synced 2025-12-06 17:23:26 +08:00
【调整】移除第三方AspNetCoreRateLimit限流组件,使用.net8自带的RateLimiter特性。
This commit is contained in:
@@ -89,10 +89,6 @@ namespace CoreCms.Net.Configuration
|
||||
/// </summary>
|
||||
public static readonly bool MiddlewareIpLogEnabled = AppSettingsHelper.GetContent("Middleware", "IPLog", "Enabled").ObjToBool();
|
||||
/// <summary>
|
||||
/// 是否开启IP限流
|
||||
/// </summary>
|
||||
public static readonly bool MiddlewareIpRateLimitEnabled = AppSettingsHelper.GetContent("Middleware", "IpRateLimit", "Enabled").ObjToBool();
|
||||
/// <summary>
|
||||
/// 记录请求与返回数据
|
||||
/// </summary>
|
||||
public static readonly bool MiddlewareRequestResponseLogEnabled = AppSettingsHelper.GetContent("Middleware", "RequestResponseLog", "Enabled").ObjToBool();
|
||||
@@ -112,14 +108,6 @@ namespace CoreCms.Net.Configuration
|
||||
/// 是否开启记录到数据库模式
|
||||
/// </summary>
|
||||
public static readonly bool MiddlewareRecordAccessLogsEnabledDbMode = AppSettingsHelper.GetContent("Middleware", "RecordAccessLogs", "EnabledDbMode").ObjToBool();
|
||||
/// <summary>
|
||||
/// 并发限制(最大并发请求数)
|
||||
/// </summary>
|
||||
public static readonly int MiddlewareConcurrencyLimiterMaxConcurrentRequests = AppSettingsHelper.GetContent("Middleware", "ConcurrencyLimiter", "MaxConcurrentRequests").ObjToInt(100);
|
||||
/// <summary>
|
||||
/// 并发限制(最大请求数)
|
||||
/// </summary>
|
||||
public static readonly int MiddlewareConcurrencyLimiterRequestQueueLimit = AppSettingsHelper.GetContent("Middleware", "ConcurrencyLimiter", "RequestQueueLimit").ObjToInt(100);
|
||||
#endregion
|
||||
|
||||
#region HangFire定时任务================================================================================
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using AspNetCoreRateLimit;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace CoreCms.Net.Core.Config
|
||||
{
|
||||
/// <summary>
|
||||
/// IPLimit限流 启动服务
|
||||
/// </summary>
|
||||
public static class IpPolicyRateLimitSetup
|
||||
{
|
||||
public static void AddIpPolicyRateLimitSetup(this IServiceCollection services, IConfiguration Configuration)
|
||||
{
|
||||
if (services == null) throw new ArgumentNullException(nameof(services));
|
||||
|
||||
// 需要将限制规则存储到高速内存中
|
||||
services.AddMemoryCache();
|
||||
// 载入配置文件的规则设置
|
||||
services.Configure<IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting"));
|
||||
// 注入计数器和规则存储
|
||||
services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();
|
||||
services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
|
||||
|
||||
// 注入计数器和规则分布式缓存存储(根据需求自行扩展)
|
||||
//services.AddSingleton<IIpPolicyStore, DistributedCacheIpPolicyStore>();
|
||||
//services.AddSingleton<IRateLimitCounterStore, DistributedCacheRateLimitCounterStore>();
|
||||
|
||||
// 用于解析上下文的注入
|
||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||
// 配置(解析器、计数器密钥生成器)
|
||||
services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
|
||||
services.AddSingleton<IProcessingStrategy, AsyncKeyLockProcessingStrategy>();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="8.0.0" />
|
||||
<PackageReference Include="Autofac.Extras.DynamicProxy" Version="7.1.0" />
|
||||
<PackageReference Include="Castle.Core" Version="5.1.1" />
|
||||
|
||||
@@ -4,10 +4,6 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CoreCms.Net.Auth\CoreCms.Net.Auth.csproj" />
|
||||
<ProjectReference Include="..\CoreCms.Net.Configuration\CoreCms.Net.Configuration.csproj" />
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using AspNetCoreRateLimit;
|
||||
using CoreCms.Net.Configuration;
|
||||
using CoreCms.Net.Loging;
|
||||
using Hangfire.Logging;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using NLog;
|
||||
using LogLevel = NLog.LogLevel;
|
||||
|
||||
namespace CoreCms.Net.Middlewares
|
||||
{
|
||||
/// <summary>
|
||||
/// 限制 ip 流量
|
||||
/// </summary>
|
||||
public static class IpLimitMiddleware
|
||||
{
|
||||
public static void UseIpLimitMiddle(this IApplicationBuilder app)
|
||||
{
|
||||
if (app == null) throw new ArgumentNullException(nameof(app));
|
||||
|
||||
try
|
||||
{
|
||||
if (AppSettingsConstVars.MiddlewareIpRateLimitEnabled)
|
||||
{
|
||||
app.UseIpRateLimiting();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
NLogUtil.WriteFileLog(LogLevel.Error, LogType.ApiRequest, "全局捕获异常", "限制ip流量异常", e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12356,6 +12356,62 @@
|
||||
最大允许上传单个文件大小(M)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:CoreCms.Net.Model.ViewModels.Options.MyRateLimitOptions">
|
||||
<summary>
|
||||
限速设置器配置文件
|
||||
用于UseRateLimiter
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:CoreCms.Net.Model.ViewModels.Options.MyRateLimitOptions.MyRateLimit">
|
||||
<summary>
|
||||
限速器节点名称
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CoreCms.Net.Model.ViewModels.Options.MyRateLimitOptions.PermitLimit">
|
||||
<summary>
|
||||
一个窗口中允许的最大允许计数器数。 在将这些选项传递给 的FixedWindowRateLimiter构造函数时,必须设置为值 > 0。
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CoreCms.Net.Model.ViewModels.Options.MyRateLimitOptions.Window">
|
||||
<summary>
|
||||
指定请求的时间范围。 必须设置为大于 Zero 将这些选项传递给 的构造函数 FixedWindowRateLimiter时的值。
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CoreCms.Net.Model.ViewModels.Options.MyRateLimitOptions.ReplenishmentPeriod">
|
||||
<summary>
|
||||
当 AutoReplenishment 设置为 true 时,内部计时器每 ReplenishmentPeriod 时间补充一次令牌数;当 false 设置为 TryReplenish 时,应用必须对限制器调用 。
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CoreCms.Net.Model.ViewModels.Options.MyRateLimitOptions.QueueLimit">
|
||||
<summary>
|
||||
排队的获取请求的最大累计允许计数。 将这些选项传递给 的FixedWindowRateLimiter构造函数时,必须设置为值 >= 0。
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CoreCms.Net.Model.ViewModels.Options.MyRateLimitOptions.SegmentsPerWindow">
|
||||
<summary>
|
||||
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CoreCms.Net.Model.ViewModels.Options.MyRateLimitOptions.TokenLimit">
|
||||
<summary>
|
||||
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CoreCms.Net.Model.ViewModels.Options.MyRateLimitOptions.TokenLimit2">
|
||||
<summary>
|
||||
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CoreCms.Net.Model.ViewModels.Options.MyRateLimitOptions.TokensPerPeriod">
|
||||
<summary>
|
||||
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:CoreCms.Net.Model.ViewModels.Options.MyRateLimitOptions.AutoReplenishment">
|
||||
<summary>
|
||||
是否自动补货
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:CoreCms.Net.Model.ViewModels.QueryMuch.QMAfterSalesItems">
|
||||
<summary>
|
||||
根据订单号查询已经售后的内容.算退货商品明细
|
||||
|
||||
66
CoreCms.Net.Model/ViewModels/Options/MyRateLimitOptions.cs
Normal file
66
CoreCms.Net.Model/ViewModels/Options/MyRateLimitOptions.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CoreCms.Net.Model.ViewModels.Options
|
||||
{
|
||||
/// <summary>
|
||||
/// 限速设置器配置文件
|
||||
/// 用于UseRateLimiter
|
||||
/// </summary>
|
||||
public class MyRateLimitOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// 限速器节点名称
|
||||
/// </summary>
|
||||
public const string MyRateLimit = "MyRateLimit";
|
||||
|
||||
/// <summary>
|
||||
/// 一个窗口中允许的最大允许计数器数。 在将这些选项传递给 的FixedWindowRateLimiter构造函数时,必须设置为值 > 0。
|
||||
/// </summary>
|
||||
public int PermitLimit { get; set; } = 100;
|
||||
|
||||
/// <summary>
|
||||
/// 指定请求的时间范围。 必须设置为大于 Zero 将这些选项传递给 的构造函数 FixedWindowRateLimiter时的值。
|
||||
/// </summary>
|
||||
public int Window { get; set; } = 10;
|
||||
|
||||
/// <summary>
|
||||
/// 当 AutoReplenishment 设置为 true 时,内部计时器每 ReplenishmentPeriod 时间补充一次令牌数;当 false 设置为 TryReplenish 时,应用必须对限制器调用 。
|
||||
/// </summary>
|
||||
public int ReplenishmentPeriod { get; set; } = 2;
|
||||
|
||||
/// <summary>
|
||||
/// 排队的获取请求的最大累计允许计数。 将这些选项传递给 的FixedWindowRateLimiter构造函数时,必须设置为值 >= 0。
|
||||
/// </summary>
|
||||
public int QueueLimit { get; set; } = 2;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int SegmentsPerWindow { get; set; } = 8;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int TokenLimit { get; set; } = 10;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int TokenLimit2 { get; set; } = 20;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int TokensPerPeriod { get; set; } = 4;
|
||||
|
||||
/// <summary>
|
||||
/// 是否自动补货
|
||||
/// </summary>
|
||||
public bool AutoReplenishment { get; set; } = false;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
// 用户访问记录(必须放到外层,不然如果遇到异常,会报错,因为不能返回流)(注意开启权限,不然本地无法写入)
|
||||
|
||||
@@ -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构造函数时,必须设置为值 > 0。
|
||||
"PermitLimit": 100,
|
||||
//指定请求的时间范围。 必须设置为大于 Zero 将这些选项传递给 的构造函数 FixedWindowRateLimiter时的值。
|
||||
"Window": 10,
|
||||
//当 AutoReplenishment 设置为 true 时,内部计时器每 ReplenishmentPeriod 时间补充一次令牌数;当 false 设置为 TryReplenish 时,应用必须对限制器调用 。
|
||||
"ReplenishmentPeriod": 2,
|
||||
//排队的获取请求的最大累计允许计数。 将这些选项传递给 的FixedWindowRateLimiter构造函数时,必须设置为值 >= 0。
|
||||
"QueueLimit": 2,
|
||||
"SegmentsPerWindow": 8,
|
||||
"TokenLimit": 10,
|
||||
"TokensPerPeriod": 4,
|
||||
//是否自动补货
|
||||
"AutoReplenishment": false
|
||||
}
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.RateLimiting;
|
||||
using Autofac;
|
||||
using Autofac.Extensions.DependencyInjection;
|
||||
using CoreCms.Net.Auth;
|
||||
@@ -31,6 +32,9 @@ using Newtonsoft.Json;
|
||||
using NLog.Web;
|
||||
using Yitter.IdGenerator;
|
||||
using LogLevel = NLog.LogLevel;
|
||||
using Microsoft.AspNetCore.RateLimiting;
|
||||
using CoreCms.Net.Model.ViewModels.Options;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
@@ -71,9 +75,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.AddClientSwaggerSetup();
|
||||
|
||||
@@ -89,15 +90,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 =>
|
||||
{
|
||||
@@ -122,6 +114,23 @@ 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 concurrencyPolicy = "Concurrency";
|
||||
|
||||
builder.Services.AddRateLimiter(_ => _
|
||||
.AddFixedWindowLimiter(policyName: concurrencyPolicy, 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);
|
||||
@@ -173,10 +182,8 @@ app.UseForwardedHeaders(new ForwardedHeadersOptions
|
||||
#region 中间件注册===================================================================
|
||||
// 获取用户访问真实ip
|
||||
app.RealIpMiddleware();
|
||||
// 启用并发限制数中间件
|
||||
app.UseConcurrencyLimiter();
|
||||
// 开启Ip限流
|
||||
app.UseIpLimitMiddle();
|
||||
// 启用速率限制中间件
|
||||
app.UseRateLimiter();
|
||||
// 记录请求与返回数据 (注意开启权限,不然本地无法写入)
|
||||
app.UseRequestResponseLog();
|
||||
// 用户访问记录(必须放到外层,不然如果遇到异常,会报错,因为不能返回流)(注意开启权限,不然本地无法写入)
|
||||
|
||||
@@ -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构造函数时,必须设置为值 > 0。
|
||||
"PermitLimit": 100,
|
||||
//指定请求的时间范围。 必须设置为大于 Zero 将这些选项传递给 的构造函数 FixedWindowRateLimiter时的值。
|
||||
"Window": 10,
|
||||
//当 AutoReplenishment 设置为 true 时,内部计时器每 ReplenishmentPeriod 时间补充一次令牌数;当 false 设置为 TryReplenish 时,应用必须对限制器调用 。
|
||||
"ReplenishmentPeriod": 2,
|
||||
//排队的获取请求的最大累计允许计数。 将这些选项传递给 的FixedWindowRateLimiter构造函数时,必须设置为值 >= 0。
|
||||
"QueueLimit": 2,
|
||||
"SegmentsPerWindow": 8,
|
||||
"TokenLimit": 10,
|
||||
"TokensPerPeriod": 4,
|
||||
//是否自动补货
|
||||
"AutoReplenishment": false
|
||||
}
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
|
||||
Reference in New Issue
Block a user