并发请求太多,服务器崩溃了?试试使用 ASP.NET Core Web API 操作筛选器对请求进行限流
1.看看 Asp.net core Webapi 项目如何优雅地使用分布式缓存2.Asp.net core Webapi 如何执行定时任务?3.试试这 6 个小技巧,提升 EF Core 性能4.C# 完美实现物联网 MQTT 数据通信5.Asp.net Webapi 的 Post 方法不能把参数加到 URL 中?试试这样写6.如何在 ASP.NET Core Web API 方法执行前后 “偷偷“ 作一些 “坏“ 事?初识 ActionFilterAttribute7.在 ASP.NET Core Web API 中使用异常筛选器捕获和统一处理异常8.操作筛选器的 1 个应用实例:自动启用事务
9.并发请求太多,服务器崩溃了?试试使用 ASP.NET Core Web API 操作筛选器对请求进行限流
10.一个简单的 ASP.NET Core 依赖注入例子,提高代码的可维护性和可扩展性11.由一个业务需求引发的对 ASP.NET 全局变量的调研及结果12.服务注册自治,降低 ASP.NET Core Web API 依赖注入的耦合度和复杂度13.ASP.NET Core 标识(Identity)框架系列(一):如何使用 ASP.NET Core 标识(Identity)框架创建用户和角色?14.ASP.NET Core 标识(Identity)框架系列(二):使用标识(Identity)框架生成 JWT Token15.ASP.NET Core 标识(Identity)框架系列(三):在 ASP.NET Core Web API 项目中使用标识(Identity)框架进行身份验证16.ASP.NET Core 标识(Identity)框架系列(四):闲聊 JWT 的缺点,和一些解决思路前言
请求限流(Rate Limiting)主要是一种用于控制客户端对服务器的请求频率的机制。
其目的是限制客户端在一定时间内可以发送的请求数量,保护服务器免受过多请求的影响,确保系统的稳定性和可靠性。
请求限流通常会基于以下几个因素来进行限制:
- 时间窗口:规定了在多长时间内允许的请求次数
- 请求配额:在时间窗口内允许的最大请求数量
- 客户端标识:根据客户端的 IP 地址、用户标识或其他标识符来进行限流
请求限流技术可以应用在很多场景,本文主要讲述 ASP.NET Core Web API 如何使用操作筛选器对请求进行限流。
Step By Step 步骤
-
创建一个ASP.NET Core Web API 项目
-
编写自定义的操作筛选器 RateLimitFilter,实现 "1s内只允许最多有一个来自同一个IP地址的请求"(留意注释)
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Caching.Memory; public class RateLimitFilter : IAsyncActionFilter { private readonly IMemoryCache memCache; // 注入的IMemoryCache public RateLimitFilter(IMemoryCache memCache) { this.memCache = memCache; } public Task OnActionExecutionAsync( ActionExecutingContext context, ActionExecutionDelegate next) { // 通过注入的 IMemoryCache 来记录用户上一次访问的时间戳 // 在分布式系统下可以改用分布式缓存来代替内存缓存 string removeIP = context.HttpContext.Connection.RemoteIpAddress!.ToString(); string cacheKey = $"LastVisitTick_{removeIP}"; // 从缓存中获取这个客户端IP地址上一次访问服务器的时间 long? lastTick = memCache.Get<long?>(cacheKey); if (lastTick == null || Environment.TickCount64 - lastTick > 1000) { // 如果缓存中不存在上一次访问时间或者上一次访问时间距离现在已经超过 1s,则通过 next 来执行后面的筛选器 memCache.Set(cacheKey, Environment.TickCount64, TimeSpan.FromSeconds(10)); return next(); } else { // 否则说明 IP 频繁访问,不执行 next,相当于终止操作方法的执行 context.Result = new ContentResult { StatusCode = 429 }; return Task.CompletedTask; } } } 代码中的内存缓存和分布式缓存可以参考本人之前文章《看看 Asp.net core Webapi 项目如何优雅地使用内存缓存》和《看看 Asp.net core Webapi 项目如何优雅地使用分布式缓存》
-
打开 Program.cs,注册这个操作筛选器
using Microsoft.AspNetCore.Mvc; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); // 注册内存缓存服务 builder.Services.AddMemoryCache(); // 注册请求限流过滤器 builder.Services.Configure<MvcOptions>(options => { options.Filters.Add<RateLimitFilter>(); }); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();
测试
启动项目,并且访问接口,如果访问频率不高的话,接口能够正常工作。
如果访问频率很高的话,服务器就会提示 "Only once per second!"
总结
在操作筛选器中,通过 await next()
来执行下一个筛选器,
如果没有下一个筛选器,程序就会执行目标操作方法。
如果不调用 await next()
,就可以终止操作方法的执行了
我是老杨,一个执着于编程乐趣、至今奋斗在一线的 10年+ 资深研发老鸟,是软件项目管理师,也是快乐的程序猿,持续免费分享全栈实用编程技巧、项目管理经验和职场成长心得!欢迎关注老杨的公众号(名称:代码掌控者),和你共同探索代码世界的奥秘!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 上周热点回顾(2.17-2.23)
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)