You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为特定API端点覆盖全局Rate Limiter?

问题:ASP.NET Core 7 限流策略覆盖冲突

我在为应用设置Rate Limiting时遇到以下问题:

  • 希望启用全局限流(覆盖所有端点)
  • 但需要为特定API端点禁用全局限流,转而应用更宽松的自定义限流策略

目前我同时配置了全局限流中间件和API专属限流中间件,但两者会同时生效,专属策略无法覆盖全局限流。相关代码如下:

builder.Services.AddRateLimiter(limiterOptions =>
{
limiterOptions.OnRejected = (context, cancellationToken) =>
{
    if (context.Lease.TryGetMetadata(MetadataName.RetryAfter, out var retryAfter))
    {
        context.HttpContext.Response.Headers.RetryAfter =
            ((int)retryAfter.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo);
    }

    context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;
    GetUserEndPoint(context.HttpContext));

    return new ValueTask();
};

limiterOptions.AddPolicy(userPolicyName, context =>
{
    var username = "anonymous user";
    if (context.User.Identity?.IsAuthenticated is true)
    {
        //await context.GetTokenAsync(JwtBearerDefaults, AuthenticationScheme, "access_token");
        username = context.Request.Headers.Authorization!;
    }

    return RateLimitPartition.GetFixedWindowLimiter(username,
        _ => new FixedWindowRateLimiterOptions
        {
            PermitLimit = myOptions.TokenLimit2,
            Window = TimeSpan.FromSeconds(myOptions.Window),
        });

});



limiterOptions.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, IPAddress>(context =>
{
    var test = context.Request.Host;

    IPAddress? remoteIpAddress = context.Connection.RemoteIpAddress;

    if (IPAddress.IsLoopback(remoteIpAddress!))
    {
        return RateLimitPartition.GetSlidingWindowLimiter
        (remoteIpAddress!,
              _ => new SlidingWindowRateLimiterOptions
              {
                  PermitLimit = myOptions.PermitLimit,
                  //QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
                  //QueueLimit = myOptions.QueueLimit,
                  Window = TimeSpan.FromSeconds(myOptions.Window),
                  SegmentsPerWindow = myOptions.SegmentsPerWindow
              });
    }

    return RateLimitPartition.GetNoLimiter(IPAddress.Loopback);
});

解决方案

在ASP.NET Core 7的限流体系中,全局限流器会默认对所有端点生效,若要让特定端点绕过全局策略并使用自定义策略,需要通过端点路由配置显式指定策略优先级,同时标记这些端点跳过全局限流。

修改步骤

  1. 将全局限流规则封装为命名策略
    移除直接设置GlobalLimiter的方式,把原全局规则转为一个命名策略,这样可以灵活控制哪些端点应用它。

  2. 在端点路由中区分策略应用

    • 对需要宽松自定义策略的API端点,显式绑定专属策略,并禁用全局限流。
    • 对其他所有端点,统一应用全局限流策略。

修改后的完整代码

服务配置部分(Program.cs)

builder.Services.AddRateLimiter(limiterOptions =>
{
    limiterOptions.OnRejected = (context, cancellationToken) =>
    {
        if (context.Lease.TryGetMetadata(MetadataName.RetryAfter, out var retryAfter))
        {
            context.HttpContext.Response.Headers.RetryAfter =
                ((int)retryAfter.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo);
        }

        context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;
        GetUserEndPoint(context.HttpContext); // 修正原代码多余的括号

        return new ValueTask();
    };

    // 定义用户专属宽松限流策略
    const string userCustomPolicy = "UserCustomPolicy";
    limiterOptions.AddPolicy(userCustomPolicy, context =>
    {
        var username = "anonymous user";
        if (context.User.Identity?.IsAuthenticated is true)
        {
            username = context.Request.Headers.Authorization!;
        }

        return RateLimitPartition.GetFixedWindowLimiter(username,
            _ => new FixedWindowRateLimiterOptions
            {
                PermitLimit = myOptions.TokenLimit2,
                Window = TimeSpan.FromSeconds(myOptions.Window),
            });
    });

    // 定义全局IP限流策略(替代原GlobalLimiter)
    const string globalIpPolicy = "GlobalIpPolicy";
    limiterOptions.AddPolicy(globalIpPolicy, context =>
    {
        IPAddress? remoteIpAddress = context.Connection.RemoteIpAddress;

        if (IPAddress.IsLoopback(remoteIpAddress!))
        {
            return RateLimitPartition.GetSlidingWindowLimiter(remoteIpAddress!,
                  _ => new SlidingWindowRateLimiterOptions
                  {
                      PermitLimit = myOptions.PermitLimit,
                      Window = TimeSpan.FromSeconds(myOptions.Window),
                      SegmentsPerWindow = myOptions.SegmentsPerWindow
                  });
        }

        return RateLimitPartition.GetNoLimiter(IPAddress.Loopback);
    });
});

端点路由配置部分(Program.cs)

app.UseRateLimiter();

// 配置需要宽松策略的API端点:禁用全局限流,仅应用专属策略
app.MapControllers()
   .RequireRateLimiting("UserCustomPolicy")
   .DisableRateLimiting(false);

// 对其他所有端点应用全局限流策略
app.MapGet("/", () => "Hello World!")
   .RequireRateLimiting("GlobalIpPolicy");

// MVC视图路由配置示例
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}")
   .RequireRateLimiting("GlobalIpPolicy");

关键说明

  • DisableRateLimiting(false):该参数设为false表示禁用全局限流,让端点只遵循显式指定的RequireRateLimiting策略。
  • 若有多个需要宽松策略的端点,可以通过路由分组统一配置:
    app.MapGroup("/api/relaxed")
       .MapControllers()
       .RequireRateLimiting("UserCustomPolicy")
       .DisableRateLimiting(false);
    

内容的提问来源于stack exchange,提问作者change world

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 01:21:01