跳到主要内容
支持与参考

速率限制与重试策略

本文说明 AnideaAI 的限流维度、分组差异和 429 处理方式。

速率限制与重试策略

本文说明 AnideaAI 的限流维度、分组差异和 429 处理方式。

限流维度总览

AnideaAI 当前主要有 5 层限制:

  1. 全局接口频率限制(按 IP)
  2. 关键接口频率限制(按 IP)
  3. 模型请求频率限制(按用户/分组)
  4. 订阅窗口限制(5 小时 / 日 / 周 / 月)
  5. 并发会话限制(按用户)

1) 全局接口频率限制(IP 维度)

默认值(管理员可改):

  • GLOBAL_API_RATE_LIMIT = 180
  • GLOBAL_API_RATE_LIMIT_DURATION = 180

可以理解为:同一 IP 在 180 秒内最多 180 次 API 请求。

命中后典型返回:

  • HTTP 429
  • error.code = RATE_GLOBAL_LIMIT

2) 关键接口频率限制(IP 维度)

用于登录、支付、OAuth 等敏感接口。

默认值(管理员可改):

  • CRITICAL_RATE_LIMIT = 20
  • CRITICAL_RATE_LIMIT_DURATION = 1200

命中后通常返回 429

3) 模型请求频率限制(用户/分组维度)

该限制默认可关闭,开启后有两个计数器:

  • 总请求数(包含失败)
  • 成功请求数(只统计状态码小于 400)

默认配置:

  • 时间窗口:1 分钟
  • 总请求上限:0(0 代表不限制)
  • 成功请求上限:1000

分组可单独覆盖:

  • 配置结构为 {"group_name": [总请求上限, 成功请求上限]}
  • 同一用户不同分组可以有不同上限

命中后典型返回:

  • HTTP 429
  • error.code = RATE_MODEL_LIMIT

4) 订阅窗口限制(额度维度)

如果账号使用订阅/月卡,会额外检查窗口额度:

  • 5 小时窗口
  • 日窗口
  • 周窗口
  • 月窗口

典型错误码:

  • QUOTA_MONTHLY_5H_EXCEEDED
  • QUOTA_MONTHLY_DAILY_EXCEEDED
  • QUOTA_MONTHLY_WEEKLY_EXCEEDED
  • QUOTA_MONTHLY_EXCEEDED

说明:很多平台会直接写 RPM/TPM。AnideaAI 这里是“请求次数窗口 + 额度窗口”双轨控制。额度窗口本质上也是对 token 消耗速度的限制。

5) 并发限制(会话维度)

当并发会话占满时,返回:

  • HTTP 429
  • error.code = RATE_CONCURRENT_FULL
  • 可能附带响应头 Retry-After(秒)

处理时应优先使用 Retry-After,不要立即重试。

不同等级/分组限制差异

AnideaAI 的差异主要来自:

  1. 账号计划差异:订阅额度窗口不同。
  2. 分组差异:模型频率限制可按分组覆盖。
  3. Key 差异:不同 Key 可绑定不同分组、模型白名单和额度。

建议做法:

  1. 生产和测试环境分开 Key。
  2. 大流量服务单独分组,避免互相挤占频率。
  3. 给高优先级业务预留独立 Key 和分组。

429 处理建议

最小重试原则

  1. 先识别 error.code,不要把所有 429 当成同一种问题。
  2. Retry-After 就严格按它等待。
  3. 没有 Retry-After 时使用指数退避 + 随机抖动。
  4. 设置最大重试次数,避免无限重试。

JavaScript 示例(指数退避)

function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}

async function requestWithRetry(doRequest, maxRetry = 5) {
for (let i = 0; i <= maxRetry; i++) {
const res = await doRequest();

if (res.status !== 429) return res;

const retryAfter = Number(res.headers.get("retry-after") || 0);
if (i === maxRetry) return res;

const baseMs = retryAfter > 0 ? retryAfter * 1000 : 500 * Math.pow(2, i);
const jitterMs = Math.floor(Math.random() * 300);
await sleep(baseMs + jitterMs);
}
}

Python 示例(指数退避)

import random
import time


def call_with_retry(do_request, max_retry=5):
for i in range(max_retry + 1):
resp = do_request()
if resp.status_code != 429:
return resp

if i == max_retry:
return resp

retry_after = int(resp.headers.get("Retry-After", "0") or "0")
base = retry_after if retry_after > 0 else 0.5 * (2 ** i)
time.sleep(base + random.uniform(0, 0.3))

相关文档

这页有帮助吗?