如何在 ASP.NET Core 中实现速率限定?

打印 上一主题 下一主题

主题 555|帖子 555|积分 1665

在 ASP.NET Core 中实现速率限定(Rate Limiting)中间件可以帮助你控制客户端对 API 的请求频率,防止滥用和过载。速率限定通常用于保护服务器资源,确保服务的稳定性和可用性。
ASP.NET Core 本身并没有内置的速率限定中间件,但你可以通过自定义中间件或使用第三方库来实现速率限定。以下是实现速率限定的几种常见方法:
1. 使用自定义中间件实现速率限定

你可以通过自定义中间件来实现速率限定。以下是一个简单的实现示例:
1.1 实现速率限定中间件
  1. using Microsoft.AspNetCore.Http;
  2. using System.Collections.Concurrent;
  3. using System.Threading.Tasks;
  4. public class RateLimitingMiddleware
  5. {
  6.     private readonly RequestDelegate _next;
  7.     private readonly int _maxRequests; // 每分钟允许的最大请求数
  8.     private readonly ConcurrentDictionary<string, RateLimiter> _rateLimiters;
  9.     public RateLimitingMiddleware(RequestDelegate next, int maxRequests)
  10.     {
  11.         _next = next;
  12.         _maxRequests = maxRequests;
  13.         _rateLimiters = new ConcurrentDictionary<string, RateLimiter>();
  14.     }
  15.     public async Task InvokeAsync(HttpContext context)
  16.     {
  17.         // 获取客户端的唯一标识(例如 IP 地址)
  18.         var clientId = context.Connection.RemoteIpAddress.ToString();
  19.         // 获取或创建速率限制器
  20.         var rateLimiter = _rateLimiters.GetOrAdd(clientId, _ => new RateLimiter(_maxRequests));
  21.         if (rateLimiter.AllowRequest())
  22.         {
  23.             await _next(context);
  24.         }
  25.         else
  26.         {
  27.             context.Response.StatusCode = StatusCodes.Status429TooManyRequests;
  28.             await context.Response.WriteAsync("请求太多。请稍后再试.");
  29.         }
  30.     }
  31. }
  32. public class RateLimiter
  33. {
  34.     private readonly int _maxRequests;
  35.     private int _requestCount;
  36.     private DateTime _windowStart;
  37.     public RateLimiter(int maxRequests)
  38.     {
  39.         _maxRequests = maxRequests;
  40.         _requestCount = 0;
  41.         _windowStart = DateTime.UtcNow;
  42.     }
  43.     public bool AllowRequest()
  44.     {
  45.         var now = DateTime.UtcNow;
  46.         // 如果当前时间窗口已过期,重置计数器
  47.         if ((now - _windowStart).TotalSeconds > 60)
  48.         {
  49.             _requestCount = 0;
  50.             _windowStart = now;
  51.         }
  52.         // 检查请求是否超出限制
  53.         if (_requestCount < _maxRequests)
  54.         {
  55.             _requestCount++;
  56.             return true;
  57.         }
  58.         return false;
  59.     }
  60. }
复制代码
2. 使用第三方库实现速率限定

假如你不想自己实现速率限定逻辑,可以使用一些现成的第三方库,例如:
2.1 AspNetCoreRateLimit

AspNetCoreRateLimit 是一个流行的 ASP.NET Core 速率限定库,支持 IP 地点、客户端 ID 和端点级别的速率限定。
安装

通过 NuGet 安装:
  1. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  2. {
  3.     app.UseMiddleware<RateLimitingMiddleware>(10); // 每分钟最多 10个请求
  4.     app.UseRouting();
  5.     app.UseEndpoints(endpoints =>
  6.                      {
  7.                          endpoints.MapControllers();
  8.                      });
  9. }
复制代码
配置

在 Startup.cs 中配置速率限定:
  1. dotnet add package AspNetCoreRateLimit
复制代码
配置文件

在 appsettings.json 中添加速率限定配置:
  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3.     // 添加内存缓存
  4.     services.AddMemoryCache();
  5.     // 配置速率限制
  6.     services.Configure<IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting"));
  7.     services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();
  8.     services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
  9.     services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
  10.     services.AddSingleton<IProcessingStrategy, AsyncKeyLockProcessingStrategy>();
  11.     services.AddInMemoryRateLimiting();
  12. }
  13. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  14. {
  15.     app.UseIpRateLimiting();
  16.     app.UseRouting();
  17.     app.UseEndpoints(endpoints =>
  18.                      {
  19.                          endpoints.MapControllers();
  20.                      });
  21. }
复制代码
3. 使用分布式缓存实现速率限定

假如你的应用是分布式的(例如部署在 Kubernetes 或多个服务器上),可以使用分布式缓存(如 Redis)来实现速率限定。
3.1 使用 Redis 实现速率限定

你可以使用 Redis 来存储每个客户端的请求计数。以下是一个简单的示例:
  1. {
  2.     "IpRateLimiting": {
  3.         "EnableEndpointRateLimiting": true,
  4.         "StackBlockedRequests": false,
  5.         "RealIpHeader": "X-Real-IP",
  6.         "ClientIdHeader": "X-ClientId",
  7.         "GeneralRules": [
  8.             {
  9.                 "Endpoint": "*",
  10.                 "Period": "1m",
  11.                 "Limit": 10
  12.                 }
  13.         ]
  14.     }
  15. }
复制代码
3.2 注册中间件

在 Startup.cs 中注册中间件:
  1. using Microsoft.AspNetCore.Http;
  2. using StackExchange.Redis;
  3. using System.Threading.Tasks;
  4. public class RedisRateLimitingMiddleware
  5. {
  6.     private readonly RequestDelegate _next;
  7.     private readonly int _maxRequests;
  8.     private readonly ConnectionMultiplexer _redis;
  9.     public RedisRateLimitingMiddleware(RequestDelegate next, int maxRequests, ConnectionMultiplexer redis)
  10.     {
  11.         _next = next;
  12.         _maxRequests = maxRequests;
  13.         _redis = redis;
  14.     }
  15.     public async Task InvokeAsync(HttpContext context)
  16.     {
  17.         var clientId = context.Connection.RemoteIpAddress.ToString();
  18.         var db = _redis.GetDatabase();
  19.         var key = $"rate_limit:{clientId}";
  20.         var requestCount = await db.StringIncrementAsync(key);
  21.         if (requestCount == 1)
  22.         {
  23.             await db.KeyExpireAsync(key, TimeSpan.FromMinutes(1));
  24.         }
  25.         if (requestCount > _maxRequests)
  26.         {
  27.             context.Response.StatusCode = StatusCodes.Status429TooManyRequests;
  28.             await context.Response.WriteAsync("请求太多。请稍后再试.");
  29.         }
  30.         else
  31.         {
  32.             await _next(context);
  33.         }
  34.     }
  35. }
复制代码
4. 总结

在 ASP.NET Core 中实现速率限定有多种方式:

  • 自定义中间件:得当简单的场景,但需要自己实现逻辑。
  • 第三方库:如 AspNetCoreRateLimit,提供了更强大的功能和灵活性。
  • 分布式缓存:如 Redis,得当分布式环境。
根据你的需求选择合适的方式,确保你的 API 可以大概有效防止滥用和过载。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

星球的眼睛

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表