ASP.NET Core 6限流策略,如何统一两种不同实现?

摘要:承载ASP.NET应用的服务器资源总是有限的,短时间内涌入过多的请求可能会瞬间耗尽可用资源并导致宕机。为了解决这个问题,我们需要在服务端设置一个阀门将并发处理的请求数量限制在一个可控的范围,即使会导致请求的延迟响应,在极端的情况会还不得不放
承载ASP.NET应用的服务器资源总是有限的,短时间内涌入过多的请求可能会瞬间耗尽可用资源并导致宕机。为了解决这个问题,我们需要在服务端设置一个阀门将并发处理的请求数量限制在一个可控的范围,即使会导致请求的延迟响应,在极端的情况会还不得不放弃一些请求。ASP.NET应用的流量限制是通过ConcurrencyLimiterMiddleware中间件实现的。(本文提供的示例演示已经同步到《ASP.NET Core 6框架揭秘-实例演示版》) [S2601]设置并发和等待请求阈值 (源代码) [S2602]基于队列的限流策略(源代码) [S2603]基于栈的限流策略(源代码) [S2604]处理被拒绝的请求(源代码) [S2601]设置并发和等待请求阈值由于各种Web服务器、反向代理和负载均衡器都提供了限流的能力,我们很少会在应用层面进行流量控制。ConcurrencyLimiterMiddleware中间件由“Microsoft.AspNetCore.ConcurrencyLimiter”这个NuGet包提供,ASP.NET应用采用的SDK(“Microsoft.NET.Sdk.Web”)并没有将该包作为默认的引用,所以我们需要手工添加该NuGet包的引用。 当请求并发量超过设定的阈值,ConcurrencyLimiterMiddleware中间件会将请求放到等待队列中,整个限流工作都是围绕这个这个队列进行的,采用怎样的策略管理这个等待队列是整个限流模型的核心。不论采用何种策略,我们都需要设置两个阈值,一个是当前允许的最大并发请求量,另一个是等待队列的最大容量。如代码片段所示,我们通过调用IServiceCollection接口的AddQueuePolicy扩展方法注册了一个基于队列(“Queue”)的策略,并将上述的两个阈值设置为2。 using App; var builder = WebApplication.CreateBuilder(args); builder.Logging.ClearProviders(); builder.Services .AddHostedService<ConsumerHostedService>() .AddQueuePolicy(options => { options.MaxConcurrentRequests = 2; options.RequestQueueLimit = 2; }); var app = builder.Build(); app .UseConcurrencyLimiter() .Run(httpContext => Task.Delay(1000).ContinueWith(_ => httpContext.Response.StatusCode = 200)); app.Run(); ConcurrencyLimiterMiddleware中间件是通过调用IApplicationBuilder的UseConcurrencyLimiter扩展方法进行注册的。后续通过调用Run扩展方法提供的RequestDelegate委托模拟了一秒钟的处理耗时。我们演示的程序还注册了一个ConsumerHostedService类型的承载服务来模拟消费API的客户端。如下面的代码片段所示,ConsumerHostedService利用注入的IConfiguration对象来提供并发量配置。当此承载服务启动之后,它会根据配置创建相应数量的并发任务持续地对我们的应用发起请求。
阅读全文