速率限制
规则
- 对 API 端点使用令牌桶,对认证/登录路由使用滑动窗口
- 优先使用 API 密钥识别调用者,回退到 IP —— 对于已认证路由绝不只依赖 IP
- 返回
429 Too Many Requests,附带 Retry-After 头(秒)和 X-RateLimit-Remaining 头
- 在 Redis(或 Serverless 下的 Upstash)中存储计数器 —— 多实例部署中切勿使用内存存储
- 设置合理的默认值:通用 API 100 req/min,认证路由 5 req/min,只读路由 1000 req/min
- Serverless 环境使用
@upstash/ratelimit —— 它原生处理 Redis 原子性和滑动窗口
- 将速率限制实现为中间件 —— 全局应用,按路由使用更严格的限制覆盖
- 对于 Next.js:在 middleware.ts 或 API 路由处理程序中进行速率限制,不要在 React 组件中执行
- 按层级(免费、专业、企业)区分限制 —— 将层级存储在 JWT 或数据库查找中
- 记录包含调用者身份的速率限制命中日志 —— 及早检测滥用模式
模式
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
const ratelimit = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.slidingWindow(10, "10 s"),
analytics: true,
});
const { success, limit, remaining, reset } = await ratelimit.limit(identifier);
避免
- 在 Serverless 或多实例设置中使用内存速率限制 —— 状态在调用之间会丢失
- 仅限应用层速率限制 —— 同时添加 CDN/边缘限制(Cloudflare、Vercel)
- 使用过于激进的限制阻止合法用户 —— 从宽松开始,根据数据收紧
- 忘记对 Webhook 和公开表单提交进行速率限制