如何在.NET Core API中限制单端点每分钟的请求次数
.NET Core API 单端点限流实现方案
下面提供两种最常用的实现方式,可根据你使用的.NET版本选择:
方案1:.NET 7+ 内置限流中间件(推荐)
.NET 7及以上版本官方已经集成了开箱即用的限流组件,无需引入第三方包:
- 第一步在
Program.cs中注册限流服务并配置策略
var builder = WebApplication.CreateBuilder(args); // 注册限流服务 builder.Services.AddRateLimiter(options => { // 定义1分钟5次请求的固定窗口限流策略 options.AddFixedWindowLimiter(policyName: "PerMin5Limit", limiterOpts => { limiterOpts.PermitLimit = 5; limiterOpts.Window = TimeSpan.FromMinutes(1); limiterOpts.QueueLimit = 0; // 超出限制直接拒绝,不排队 }); // 配置限流触发后的返回内容 options.OnRejected = async (context, token) => { context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests; await context.HttpContext.Response.WriteAsync("请求过于频繁,请1分钟后重试", cancellationToken: token); }; }); builder.Services.AddControllers(); // 其他服务注册逻辑... var app = builder.Build(); app.UseRouting(); app.UseRateLimiter(); // 限流中间件必须放在路由匹配之后、端点映射之前 app.MapControllers(); app.Run();
- 第二步给目标端点绑定限流策略,直接在对应Action上加特性即可:
[ApiController] [Route("api/[controller]")] public class TestController : ControllerBase { [HttpGet] // 你要限流的目标端点 [EnableRateLimiting("PerMin5Limit")] public IActionResult TestEndpoint() { return Ok("请求成功"); } }
方案2:自定义ActionFilter实现(兼容.NET 6及更低版本)
如果使用的是低于.NET 7的版本,可以自己实现轻量的限流过滤器:
- 第一步创建限流特性类:
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Caching.Memory; public class RateLimitAttribute : ActionFilterAttribute { private readonly int _maxRequestCount; private readonly TimeSpan _limitWindow; public RateLimitAttribute(int maxRequestCount, int windowSeconds) { _maxRequestCount = maxRequestCount; _limitWindow = TimeSpan.FromSeconds(windowSeconds); } public override void OnActionExecuting(ActionExecutingContext context) { // 从请求容器获取缓存服务 var cache = context.HttpContext.RequestServices.GetRequiredService<IMemoryCache>(); // 用客户端IP+请求路径作为唯一计数键,按不同用户不同端点单独计数 var clientIp = context.HttpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown_ip"; var cacheKey = $"rate_limit:{clientIp}:{context.HttpContext.Request.Path}"; // 读取当前计数 var currentCount = cache.Get<int>(cacheKey); if (currentCount >= _maxRequestCount) { context.Result = new ContentResult { StatusCode = StatusCodes.Status429TooManyRequests, Content = "请求过于频繁,请1分钟后重试" }; return; } // 更新计数,缓存过期时间和限流窗口保持一致 cache.Set(cacheKey, currentCount + 1, _limitWindow); base.OnActionExecuting(context); } }
- 第二步在
Program.cs注册依赖的内存缓存服务:
builder.Services.AddMemoryCache(); builder.Services.AddControllers();
- 第三步给目标端点加特性即可:
[HttpGet] [RateLimit(5, 60)] // 参数:最大请求数、限流窗口秒数,即1分钟5次 public IActionResult TestEndpoint() { return Ok("请求成功"); }
注意:如果是分布式多实例部署的场景,方案2需要把
IMemoryCache替换为IDistributedCache(分布式缓存),避免各实例单独计数导致限流规则不准。
内容的提问来源于stack exchange,提问作者Gabriel Andrade
相关产品推荐
相关产品推荐

