@convex-dev/rate-limiter

中文文档
0.4.3发布于 2026/10/30Apache-2.0TypeScriptES Module近 30 天下载 301.3万

Convex 的限速器组件 。 定义并使用应用层率限制. 类型安全,交易性,公平性,安全性,可塑性硬化到规模.

中文使用文档
文档目录20 节
  1. 预先要求: Convex
  2. 安装
  3. 定义利率限制 :
  4. 战略:
  5. 使用量
  6. 使用简单的全局率限制 :
  7. 用户比率限制 :
  8. 设定自定义计数
  9. 自动掷出
  10. 检查一个速率限制而不消耗
  11. 信贷能力恢复到利率限度
  12. 重设费率限制
  13. 内置/ 动态定义费率限制
  14. 使用反应钩
  15. 直接获取当前值
  16. 避免同步更新的争议
  17. 用硬块限制比例
  18. 保留能力:
  19. 添加焦躁状态
  20. 更多资源

Convex 限速器组件

npm version

这一构成部分规定了应用水平税率限制.

茶师:

const rateLimiter = new RateLimiter(components.rateLimiter, {
  freeTrialSignUp: { kind: "fixed window", rate: 100, period: HOUR },
  sendMessage: { kind: "token bucket", rate: 10, period: MINUTE, capacity: 3 },
});

// Restrict how fast free users can sign up to deter bots
const status = await rateLimiter.limit(ctx, "freeTrialSignUp");

// Limit how fast a user can send messages
const status = await rateLimiter.limit(ctx, "sendMessage", { key: userId });

// Use the React hook to check the rate limit
const { status, check } = useRateLimit(api.example.getRateLimit, { count });

使用详情见下文.

利率限制是什么?

限制利率是控制行动频率的技术 通常在服务器上 有多种实现 大部分在网络层运行.

如何限制应用层比率?

应用层限制率发生在您的应用代码中 处理认证、授权和其他业务逻辑。 它允许你 更公平地执行政策。 这不是第一次 尖端DDOS攻击的防线(幸好这是极好的) ),但将服务于大多数现实世界使用的案例.

这种办法有什么区别?

  • 类型安全使用:您不会意外错失一个速率限制名称.
  • 用于固定窗口或符号桶算法的配置 .
  • 高效存储和计算:存储与请求不相称.
  • 配置限制,适用于背景中可扩展性的更新.
  • 交易评价:如果您 变异失败 .
  • 通过信用"保全"提供公平性担保:使自己免于指数化 备份.
  • 通过可配置的“滚动”或“爆发”津贴 capacity。 。 。 .
  • 故障关闭, 不打开 : 当交通超过时, 避免连锁故障 利率限制.

见相关的 堆叠站 为了更多 细节和背景.

预先要求: Convex

你需要一个现有的 Convex 项目来使用组件。 Convex 是一个主机 后端平台,包括数据库、无服务器功能和多一个吨 可以学习 这里。 。 。 .

运行 npm create convex 或遵循其中任何一条 快速启动 来设置一个.

安装

安装组件包 :

npm install @convex-dev/rate-limiter

创建一个 convex.config.ts 应用程序中的文件 convex/ 文件夹并安装 通过调用 use数字 :

// convex/convex.config.ts
import { defineApp } from "convex/server";
import rateLimiter from "@convex-dev/rate-limiter/convex.config.js";

const app = defineApp();
app.use(rateLimiter);

export default app;

定义利率限制 :

import { RateLimiter, MINUTE, HOUR } from "@convex-dev/rate-limiter";
import { components } from "./_generated/api";

const rateLimiter = new RateLimiter(components.rateLimiter, {
  // One global / singleton rate limit, using a "fixed window" algorithm.
  freeTrialSignUp: { kind: "fixed window", rate: 100, period: HOUR },
  // A per-user limit, allowing one every ~6 seconds.
  // Allows up to 3 in quick succession if they haven't sent many recently.
  sendMessage: { kind: "token bucket", rate: 10, period: MINUTE, capacity: 3 },
  failedLogins: { kind: "token bucket", rate: 10, period: HOUR },
  // Apply updates asynchronously for eventual consistency.
  llmTokenBudget: {
    kind: "token bucket",
    rate: 10,
    period: HOUR,
    applyUpdates: "asynchronously",
  },
  // Use sharding to increase throughput without compromising on correctness.
  llmTokens: { kind: "token bucket", rate: 40000, period: MINUTE, shards: 10 },
  llmRequests: { kind: "fixed window", rate: 1000, period: MINUTE, shards: 10 },
});
  • 如果您想要定义不同的 如果密钥不重合的话 费率会分开.
  • 单位: period 数以毫秒计. MINUTE 以上为 60000。 。 。 .

战略:

这个 token bucket 方法为总体消费提供了保障 页:1 rate 百分比 period 添加符号,同时允许未使用 累积( 如“ 翻转 ” 分钟) 到一些 capacity 数值。 这么说吧 通常每分钟发送10个,容量20个,然后每2个 几分钟你就可以发送20, 或者在最后两分钟你只发送5,你 现在可以发送15.

这个 fixed window 不同的方法是: 指示牌在 一次,两次 period 毫秒长. 类似地可以累积"翻转" 符号最多 a capacity (对 rate 两个费率限额 (战略) 您可以指定自定义 start 时间,例如如果您想要时段 以在一天的特定时间重设。 默认是随机帮助空间 退出正在重试的请求.

使用量

使用简单的全局率限制 :

const { ok, retryAfter } = await rateLimiter.limit(ctx, "freeTrialSignUp");
  • ok 是否成功消耗了资源
  • retryAfter 当它将来成功的时候.

说明: 如果您有许多客户使用 retryAfter 决定何时 重试,防御 雷鸣群起 以 添加一些内容 抖动或使用 reserve 函数 讨论 下级。 。 。 .

用户比率限制 :

使用 key 以使用特定于一些用户 / 团队 / 会话 ID 等的速率限制.

const status = await rateLimiter.limit(ctx, "sendMessage", { key: userId });

设定自定义计数

默认情况下,每次呼叫 limit 以一个单位计算。 过 count 来定制.

// Consume multiple in one request to prevent rate limits on an LLM API.
const status = await rateLimiter.limit(ctx, "llmTokens", { count: tokens });

自动掷出

默认它会返回 { ok, retryAfter }自动投出 当超过限制时,使用 throws它会扔出一个 ConvexError 与 RateLimitError 数据(data: {kind, name, retryAfter}(而不是返回) 何时 ok 是虚假的.

// Automatically throw an error if the rate limit is hit
await rateLimiter.limit(ctx, "failedLogins", { key: userId, throws: true });

检查一个速率限制而不消耗

const status = await rateLimiter.check(ctx, "failedLogins", { key: userId });

信贷能力恢复到利率限度

// Give back the token that was consumed for a request that failed.
await rateLimiter.credit(ctx, "sendMessage", { key: userId });

// Credit a custom count, e.g. to settle a reservation made up-front.
await rateLimiter.credit(ctx, "llmTokens", { count: reserved - used });

它的顶端是 capacity (违约) rate) (中文(简体) ). 任何多余的都被丢弃.

对a 软化 费率限制, 两个随机 硬块被选中,信用被分成两部分,这样它们就完了 尽可能接近相同值。 任何剩余信用都被放弃.

重设费率限制

// Reset a rate limit on successful login
await rateLimiter.reset(ctx, "failedLogins", { key: userId });

内置/ 动态定义费率限制

// Use a one-off rate limit config (when not named on initialization)
const config = { kind: "fixed window", rate: 1, period: SECOND };
const status = await rateLimiter.limit(ctx, "oneOffName", { config });

使用反应钩

您可以使用 React 钩子检查浏览器代码中的速率限制 .

首先,定义服务器 API 以获得速率限制值 :

// In convex/example.ts
export const { getRateLimit, getServerTime } = rateLimiter.hookAPI(
  "sendMessage",
  {
    // Optionally provide a key function to get the key for the rate limit
    key: async (ctx) => await getUserId(ctx),
    // To allow the client to provide the key, pass a function that takes the key from the client
    key: async (ctx, keyFromClient) => {
      await ensureUserCanUseKey(ctx, keyFromClient);
      return keyFromClient;
    },
  },
);

然后,使用反应钩检查速率限制:

function App() {
  const { status: { ok, retryAt }, check } = useRateLimit(api.example.getRateLimit, {
    // [recommended] Allows the hook to sync the browser and server clocks
    getServerTimeMutation: getServerTime,
    // [optional] The number of tokens to wait on
    count: 1,
  });

  // If you want to check at specific times and get the concrete value:
  const { value, ts, config, ok, retryAt } = check(Date.now(), count);

直接获取当前值

如果您想知道, 您可以直接获取利率限制的当前值 上次更新的具体值和时间戳.

const { config, value, ts } = await rateLimiter.getValue(ctx, "sendMessage", {
  key: userId,
});

{\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}你还可以用 calculateRateLimit 以计算给定值 时间戳 :

import { calculateRateLimit } from "@convex-dev/rate-limiter";

const { config, value, ts } = calculateRateLimit(
  { value, ts },
  config,
  Date.now(),
  count || 0,
);

避免同步更新的争议

当许多请求同时出现时,他们都可以试图修改 数据库中的数值相同。 由于Convex提供强大的交易 永远不覆盖对方, 所以你不必担心利率 限制比它更经常成功。 然而,当有高 有关这些价值的争论,它引起 乐观货币控制冲突。 。 。 . Convex用后退多次自动重试这些,但它是 最好还是避开他们.

使用 自动同步 限速器的模式有助于增加 在避免OCC冲突的同时,限制费率。 在那个 RateLimiter 配置, 设置 极限 applyUpdates 改为 "asynchronously"数字 :

const rateLimiter = new RateLimiter(components.rateLimiter, {
  llmTokens: {
    kind: "token bucket",
    rate: 40000,
    period: MINUTE,
    applyUpdates: "asynchronously",
  },
});

更新不是在交易中更新利率限制,而是放在队列中 适用于背景 批发工人。检查限制 在一个突变中读取从一个陈旧的数据库快照, 所以这些速率限制 呼声永远不会与同时出现的作者相冲突.

取舍是同步极限最终一致. 一个大 在工人申请足够之前,同时召集人的突围都能够成功 消耗以阻断新呼叫者,这会导致限制变为负数. 说明 消费仍然被计算在内。 当同步更新超过时 未来的请求会被拒绝,直到足够 从负结余中恢复过来的时间已经过去.

如果需要执行精确的瞬间上限 用于您的使用案例,请考虑 使用 shards。 。 。 .

用硬块限制比例

在保持交易性的同时增加吞吐量的一种办法是: "硬"的利率限制。 我们把总容量拆成一桶, 或者说"硬" 当我们去使用一些 能力,我们检查一个随机 坚硬.1个 有时我们会倒霉而得到 在别处有产能的时候,我们绝对不会违反 限制的上限.

const rateLimiter = new RateLimiter(components.rateLimiter, {
  llmTokens: { kind: "token bucket", rate: 40000, period: MINUTE, shards: 10 },
  llmRequests: { kind: "fixed window", rate: 1000, period: MINUTE, shards: 10 },
});

在这里,我们用10个硬板处理1000个QPM. 如果你想要一些粗糙的数学 猜测要添加多少个硬块, 接受您期望的每秒最大查询 以2除以2。 每个硬体也有五(理想为十)或 增加容量。 在这种情况下,我们有10个(比率/硬度),不期望正常 流量将超过~20QPS.

提示: 如果您想要一个像 { rate: 100, period: SECOND } 而你们是 在总体周期中灵活,然后通过提高费率来降低 并按比例计算以获得足够的硬度和每个硬度的容量: { shards: 50, rate: 250, period: 2.5 * SECOND } 或更好: { shards: 50, rate: 1000, period: 10 * SECOND }。 。 。 .

注意: 同步率限制不能被硬化 .

两人的力量

我们实际上走得更远 检查两个硬盘,用一个 能力较强,能够保持相对平衡 两种技术的力量。 。 。 . 如果两者都不够 他们自己的.

重设被压抑的利率限制

重设被压抑的速率限制将会读写到所有被压抑的 如果有许多同意的请求,则可能造成OCC冲突。 若您的使用大小写 涉及频繁重播, 考虑 同步应用更新 而不是软化.

保留能力:

你也可以允许它 reserve 消除饥饿的能力 请求.

当你提前预留能力时,合同是 你可以运行你的 在指定时间运行(通过 retryAfter 字段),此时您 不必重新检查费率限额. 你的能力已经被"警告"了.

使用此操作, 您可以排队操作许多操作, 操作会以空格运行 间隔,最大限度地利用费率限额.

详细情况 堆叠站。 。 。 .

const myAction = internalAction({
  args: {
    //...
    skipCheck: v.optional(v.boolean()),
  },
  handler: async (ctx, args) => {
    if (!args.skipCheck) {
      // Reserve future capacity instead of just failing now
      const status = await rateLimiter.limit(ctx, "llmRequests", {
        reserve: true,
      });
      if (status.retryAfter) {
        return ctx.scheduler.runAfter(
          status.retryAfter,
          internal.foo.myAction,
          {
            // When we run in the future, we can skip the rate limit check,
            // since we've just reserved that capacity.
            skipCheck: true,
          },
        );
      }
    }
    // do the operation
  },
});

添加焦躁状态

当用户同时出现太多时, 会导致网络拥堵, 数据库 以不必要的高比率消耗其他共享资源. 相反,我们可以在下一个周期内返回一个随机时间来重试。 希望这样 这是不常见的。 这种技术被指为添加"热"

简单的执行可以看起来是:

const retryAfter = status.retryAfter + Math.random() * period;

对于固定窗口,我们也通过选择起始时间来引入随机性 如果 没有提供配置. start 。 这可以防止所有客户端被淹没 午夜请求并呼唤你.

更多资源

看看这里的完整例子。 。 。 .

见 本条 更多信息 关于使用和先进模式,例如:

  • 不同速率的限制策略如何在引擎盖下运作.
  • 在一次交易中使用多利率限制.
  • 限制匿名用户的费率.

版本与发布记录

@convex-dev/rate-limiter 共发布 28 个版本,首次发布于 2024/10/22;过去 12 个月发布了 9 个版本。

版本发布日期距今
0.4.3latest2026/10/3011 天前
0.4.22026/10/101 个月前
0.4.12026/10/071 个月前
0.4.1-alpha.0alpha2026/09/241 个月前
0.4.02026/09/151 个月前
0.4.0-alpha.02026/09/121 个月前

关于 @convex-dev/rate-limiter 的常见问题

@convex-dev/rate-limiter 是什么?

Convex 的限速器组件 。 定义并使用应用层率限制. 类型安全,交易性,公平性,安全性,可塑性硬化到规模.

如何安装 @convex-dev/rate-limiter?

在项目目录运行 npm install @convex-dev/rate-limiter,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:convex(^1.43.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@convex-dev/rate-limiter 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@convex-dev/rate-limiter 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@convex-dev/rate-limiter 可以商用吗?

@convex-dev/rate-limiter 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@convex-dev/rate-limiter 的下载量有多少?

根据 npm 官方下载统计,@convex-dev/rate-limiter 在 2026/10/11 – 2026/11/09 这 30 天内被下载 3,013,019 次,日均约 100,434 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@convex-dev/rate-limiter 还在维护吗?

最新版本 0.4.3 发布于 2026/10/30(11 天前);至今共发布 28 个版本,其中过去 12 个月发布了 9 个;首次发布于 2024/10/22。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。