.NET 7 限流实现:基于IP地址的请求频次限制
如何将现有固定窗口限流器改为基于IP地址限流(10秒内每个IP允许2次请求)
要实现按IP地址独立限流,你需要将全局统一的固定窗口限流器替换为分区限流器(PartitionedRateLimiter),让每个IP地址拥有专属的限流规则实例。具体修改如下:
核心修改思路
分区限流器会根据你指定的键(这里是客户端IP)为每个IP创建独立的限流窗口,确保不同IP的请求互不干扰,各自遵守「10秒内2次请求」的规则。
修改后的完整代码
app.UseRateLimiter(new RateLimiterOptions { OnRejected = (context, _) => { if (context.Lease.TryGetMetadata(MetadataName.RetryAfter, out var retryAfter)) { context.HttpContext.Response.Headers.RetryAfter = ((int)retryAfter.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo); app.Logger.LogWarning("请求超出限流阈值,请在{RetryAfter}秒后重试", retryAfter.TotalSeconds); } context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests; return new ValueTask(); } } // 每个IP在10秒内允许2次请求 .AddPartitionedRateLimiter("ip-fixed-window", context => { // 获取客户端IP地址,处理IP为空的边界情况 var ipAddress = context.Connection.RemoteIpAddress?.ToString() ?? "unknown-ip"; // 为每个IP创建独立的固定窗口限流规则 return RateLimitPartition.GetFixedWindowLimiter(ipAddress, _ => new FixedWindowRateLimiterOptions(2, window: TimeSpan.FromSeconds(10), queueProcessingOrder: QueueProcessingOrder.OldestFirst, queueLimit: 0, autoReplenishment: true)); })); app.MapControllers().RequireRateLimiting("ip-fixed-window");
关键代码说明
- 替换限流注册方法:用
AddPartitionedRateLimiter替代原有的AddFixedWindowLimiter,并指定分区键为客户端IP地址 - IP地址获取:通过
context.Connection.RemoteIpAddress提取客户端IP,为避免空引用,添加了?? "unknown-ip"的默认值 - 独立规则实例:
RateLimitPartition.GetFixedWindowLimiter会为每个IP创建单独的固定窗口限流实例,保证各IP的限流统计相互独立
内容的提问来源于stack exchange,提问作者nop
相关产品推荐
相关产品推荐

