Skip to content
bitzorcas
EN

Concept

限流

分区限流 — 三种 ASP.NET Core 限流策略(令牌桶、滑动窗口、固定窗口),支持每租户和每调用方分区。

Last updated

BitzOrcas 使用 ASP.NET Core 内置限流,配合租户 + 调用方分区策略。每个租户/调用方对获得独立的计数桶,防止应用调用方共享匿名桶。

三种策略

策略算法窗口用途
userPolicy令牌桶1 分钟通用 REST API 端点
sensitivePolicy滑动窗口1 分钟登录、OTP、密码重置
fixedPolicy固定窗口1 分钟内部/低频服务

分区键格式

{tenant_id}:{user_id|client_id}

这确保应用调用方(有 client_id 但无 user_id)被正确分区,而非全部落入”匿名”桶。

策略参数

userPolicy(令牌桶)

new TokenBucketRateLimiterOptions
{
TokenLimit = 2,
TokensPerPeriod = 2,
ReplenishmentPeriod = TimeSpan.FromMinutes(1),
QueueLimit = 0,
AutoReplenishment = true,
}

每分钟 2 个请求,无排队。

sensitivePolicy(滑动窗口)

new SlidingWindowRateLimiterOptions
{
Window = TimeSpan.FromMinutes(1),
SegmentsPerWindow = 4,
PermitLimit = 5,
QueueLimit = 0,
}

每分钟 5 个请求——滑动窗口防止边界突发攻击。

fixedPolicy(固定窗口)

new FixedWindowRateLimiterOptions
{
Window = TimeSpan.FromMinutes(1),
PermitLimit = 10,
AutoReplenishment = true,
}

每分钟 10 个请求——简单可预测,适用于内部服务。

429 响应

所有限流请求返回 RFC 9457 ProblemDetails:

{
"type": "https://docs.bitzsoft.com/problems/rate-limit-exceeded",
"title": "Too Many Requests",
"status": 429,
"detail": "Rate limit exceeded.",
"errorCode": "RateLimit.Exceeded",
"retryAfter": 60
}

包含 HTTP 头:

  • Retry-After: 60
  • X-RateLimit-Remaining: 0(可用时)

端点中使用

app.MapPost("/api/notes", async (...) => ...)
.RequireRateLimiting("userPolicy");
app.MapPost("/api/auth/login", async (...) => ...)
.RequireRateLimiting("sensitivePolicy");

中间件顺序

限流中间件放在管道中授权之后

ExceptionHandler → CorrelationId → Auth → DelegationToken
→ TenantResolution → Audit → Authorization → RateLimiter → Endpoints

生产环境考量

对于多实例部署,考虑:

  • Redis DistributedRateLimiter — 跨实例共享计数器
  • 网关级限流 — YARP/Envoy/Nginx 在到达 API 之前限流
  • 每租户限流计划 — 从计费订阅配置可配限制