跳到主要内容

速率限制

Chastify 限制扩展 API 流量,以保护锁定会话、存储、设备和通知系统。

速率限制适用于通过 Chastify 路由的 iframe 桥接流量和使用开发者 API 密钥进行的后端调用。

当前扩展桶

存储桶限制典型端点
读取300/minsession.getstate.getmetadata.get、文件读取、常规操作状态
写入120/min后端状态写入、元数据更新、常规操作配置、服务器验证运行创建
上传10/min运行时和设置文件上传
操作30/min锁定操作、设备命令、自定义日志、自定义通知、服务器验证结果结算
令牌30/minIframe 会话启动/身份验证令牌生成

限值是在一分钟的时间窗口内评估的。

备注

这些是平台默认设置。Chastify 管理员/站点所有者可以为官方或访问量异常高的扩展程序配置单独的扩展程序覆盖设置。覆盖设置存储在扩展程序应用程序配置中,并会在 Redis 中短暂缓存,以便快速查找请求路径。

信息

上传和操作存储桶的容量比读取/状态存储桶的容量要小。上传操作会占用存储空间和带宽。操作会影响锁定状态、设备、通知和用户可见的历史记录。

钥匙的计数方式

速率限制密钥包括:

  • 当第一方 UI 调用端点时,已验证的 Chastify 用户 ID
  • 当您的后端调用扩展会话端点时,需要开发者 API 密钥 ID。
  • 匿名或未经认证路径的 IP 地址
  • 目标 sessionIdlockId(如有)

这意味着一个嘈杂的扩展会话不应该消耗掉整个全局扩展 API 预算。

您的 iframe 或后端应将 429 Too Many Requests 视为正常的可重试条件。

对于重复失败,使用指数退避算法:

async function callWithBackoff<T>(fn: () => Promise<T>, attempts = 4): Promise<T> {
let delayMs = 500;

for (let attempt = 1; attempt <= attempts; attempt += 1) {
try {
return await fn();
} catch (error: any) {
const status = error?.status ?? error?.response?.status;
if (status !== 429 || attempt === attempts) throw error;

await new Promise((resolve) => setTimeout(resolve, delayMs));
delayMs *= 2;
}
}

throw new Error("request_failed");
}

Iframe 桥接指南

对于 iframe 桥接客户端:

  • 除非需要最新的锁定数据,否则将 session.get 结果缓存到页面生命周期内。
  • 将瞬态 UI 更改存储在本地,并将可信更改发送到后端。
  • 避免快速轮询循环。最好采用用户触发的读取操作或较慢的刷新间隔。

后端保存防抖示例:

let saveTimer: number | undefined;

function scheduleStateSave(data: Record<string, unknown>) {
window.clearTimeout(saveTimer);
saveTimer = window.setTimeout(() => {
fetch("/your-extension-backend/state", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
}).catch(console.error);
}, 500);
}

后端扩展指南

对于使用开发者 API 密钥进行的后端调用:

  • 特权操作需经服务器验证并由用户触发。
  • 仅可通过开发者 API 凭据从后端使用 PUT/PATCH /api/extensions/sessions/:sessionId/state
  • 如果第一次尝试可能成功,请不要盲目地重试锁定操作。
  • 使游戏/挑战结算具有幂等性,并带有运行 ID。
  • 仅当用户明确提交文件时才上传文件。
  • 如果需要更高频率的遥测数据,请自行存储外部记录。
注意

切勿为了弥补未经验证的浏览器调用而提高操作限制。浏览器 iframe 代码不可信。敏感数据变更应在调用 Chastify 之前由后端进行验证。

我应该期待收到哪一桶水?

常见例子:

  • GET /api/extensions/sessions/:sessionId 使用读取桶。
  • GET /api/extensions/sessions/:sessionId/state 使用读取桶。
  • PUT/PATCH /api/extensions/sessions/:sessionId/state 使用写入桶。
  • POST /api/extensions/sessions/:sessionId/files 使用上传存储桶。
  • POST /api/extensions/sessions/:sessionId/action 使用操作桶。
  • POST /api/extensions/sessions/:sessionId/device-command 使用操作桶。
  • POST /api/extensions/sessions/:sessionId/logs/custom 使用操作桶。
  • POST /api/extensions/sessions/:sessionId/notifications/custom 使用操作桶。
  • GET /api/extensions/sessions/:sessionId/auth 使用令牌桶。

未来颗粒桶

目前的分类范围较广。随着开发者 API 的发展,Chastify 可能会进一步细分分类,例如:

  • state.write
  • metadata.write
  • lock.action
  • notifications.custom
  • device.command
  • files.upload

当官方或已批准的高流量扩展程序有正当理由需要时,Chastify 管理员/站点所有者可以提高每个扩展程序的限制。设计客户端时,应确保 429 的处理方式是通用的,不依赖于具体的存储桶名称或固定的平台默认值。