.net core 使用中间件实现限流

https://docs.microsoft.com/en-us/aspnet/core/performance/caching/memory?view=aspnetcore-6.0
假定我们希望所有的接口1分钟内只允许访问10次,因为所有的请求都需要走中间件,所以这个功能我们可以通过中间件来实现

通过设置以下三个响应头让客户端明确知道访问信息

X-RateLimit-Limit:同一时间段内的最大访问个数
X-RateLimit-Retry-After:超出限制后,再次正常访问时间
X-RateLimit-Remaining:同一时间段剩余请求次数
访问超限返回429状态码

using Microsoft.Extensions.Caching.Memory;

namespace EFCoreJWT.Middleware
{
    public class RequestLimitMiddleWare
    {
        private readonly IMemoryCache memoryCache;
        private readonly RequestDelegate requestDelegate;
        public const int Limit = 10;

        public RequestLimitMiddleWare(RequestDelegate requestDelegate, IMemoryCache memoryCache)
        {
            this.requestDelegate = requestDelegate;
            this.memoryCache = memoryCache;
        }

        public async Task InvokeAsync (HttpContext context)
        {
            var requestKey = $"{context.Request.Method}-{context.Request.Path}";

            int requestCount = 0;

            var cacheOptions = new MemoryCacheEntryOptions()
            {
                AbsoluteExpiration = DateTime.Now.AddMinutes(1)
            };

            if (memoryCache.TryGetValue(requestKey,out requestCount))
            {
                if (requestCount<Limit)
                {
                    await ProcessRequest(context, requestKey, requestCount, cacheOptions);
                }
                else 
                {
                    context.Response.Headers["X-RateLimit-Retry-After"] = cacheOptions.AbsoluteExpiration?.ToString();
                    context.Response.StatusCode = StatusCodes.Status429TooManyRequests;
                }
            }
            else
            {
                await ProcessRequest(context,requestKey,requestCount,cacheOptions);
            }
        }


        private async Task ProcessRequest(HttpContext context,string requestKey,int requestCount,MemoryCacheEntryOptions memoryCacheEntryOptions)
        {
            requestCount++;

            memoryCache.Set(requestKey,requestCount,memoryCacheEntryOptions);

            context.Response.Headers["X-RateLimit-Limit"] = Limit.ToString();

            context.Response.Headers["X-RateLimit-Remaining"] = (Limit - requestCount).ToString();

            await requestDelegate(context);

        }
    }
}

因为我们是用内置的IMemoryCache,所以需要在programe中注入

builder.Services.AddMemoryCache();
#添加中间件
app.UseMiddleware<RequestLimitMiddleWare>();

你可能感兴趣的:(.netCore,.netcore,开发语言)