详细解释
RPS(Requests Per Second,每秒请求数) 是后端/网关工程师眼中最自然的吞吐单位,和 Web API 世界其他服务(HTTP REST、数据库 QPS)一致。RPM 是给业务/计费看的”分钟粒度”,RPS 是给做架构的人看的”秒粒度”。
一个典型的容量规划场景:
预估峰值 1200 RPM → 即 1200 / 60 = 20 RPS。平均每个请求在网关侧要占 200 ms → 并发数 = RPS × Latency = 20 × 0.2 = 4 个”一直在飞的请求”(并发连接池 = 4 就够)。如果加峰值缓冲按 3× 设计 → 并发 12,网关限流按 30 RPS 设置。
RPS 与 RPM / 并发数的换算三角(核心必背)
三个指标之间知二推一:
| 公式 | 示例 |
|---|---|
| RPS = RPM / 60 | 1200 RPM = 20 RPS |
| 并发 = RPS × 平均耗时(秒) | 20 RPS × 0.5s = 10 并发 |
| RPM = 并发 × (60 / 平均耗时秒) | 10 并发 × 120 次/分 = 1200 RPM |
为什么 RPS 比 RPM 更有用:因为 限流(Rate Limit) 本质是”令牌桶”算法,令牌桶的基本时间粒度是秒级甚至毫秒级,RPM 是”用 60 秒窗口平滑后的 RPS”。突发流量下,如果一个用户 1 秒内打了 60 个请求(RPS=60),之后 59 秒都不发请求——平均 RPM 还是 60,完全合法;但你的系统在那 1 秒被打爆了。所以做限流时:
- 对外承诺写 RPM(用户好理解)
- 对内网关配置一定要写 RPS / 并发 / TPM 三重组合(甚至还要加 RPD / TPD 日维度)
真实 API 网关的”四层限流”典型配置
以 唯元智创 聚合网关为例,单个 API Key 默认同时受以下 4 层约束(按作用时间从短到长):
| 限流维度 | 默认值(Pro Tier) | 作用窗口 | 防止什么 |
|---|---|---|---|
| 并发并发数 | 50 | 瞬时(正在进行中的请求总数) | 瞬时打满连接池 |
| RPS | 100 | 1 秒滑窗 | 秒级突发(爬虫/脚本一瞬间刷) |
| RPM / TPM | 3000 / 2,000,000 | 1 分钟滑窗 | 分钟级持续打满(与 速率限制 定义一致) |
| RPD / TPD | 100,000 / 50,000,000 | 24 小时固定窗 | 一天打爆账单(配合 消费上限 双重保障) |
任何一层超限都会返回 HTTP 429。用户侧应配合 指数退避 + 抖动(Exponential Backoff) 重试。
压测时如何正确报告 RPS
压测报告里只写一个”RPS=XX”是不专业的,至少附这 5 件事:
- P95 Latency:此时 95 分位延迟是多少毫秒。RPS 高但 P95 爆了等于没意义。
- 错误率:此时 HTTP 4xx/5xx 占比 < 1%?
- 请求分布:是 chat/completions(长)还是 embeddings(短)?平均输入/输出 Token 数?
- 是否流式(Streaming):流式和非流式的 RPS 数字完全不可比(流式一个请求占连接久得多)。
- 测试时长:至少跑 10–30 分钟,排除冷启动/缓存热身偏差。
常见问题
为什么我压测到 RPS=30 就上不去了,明明 RPM 限流是 3000?
3000 RPM ≈ 50 RPS,你 30 就上不去通常有三种原因(按概率排):① 你的客户端并发不够(并发 = RPS × 耗时,如果耗时 0.5s 你需要 15 并发;你的池子只有 10,就只能到 20 RPS);② 被RPS 秒级限流挡住了(厂商没写在文档里但实际存在);③ 上游模型端 排队延迟 飙升。排查顺序:先加大客户端并发池 → 看 429 响应头里的
Retry-After / X-RateLimit-* 字段 → 再查账单面板。流式输出的 RPS 怎么定义?
标准定义还是”每秒完整完成并关闭连接的请求数”——不是 SSE 的每秒 chunk 数。所以流式请求平均占用连接时间更长(比如 5–10s vs 非流式 0.5s),相同并发数下流式 RPS 只有非流式的 1/10 ~ 1/20。做容量规划时必须分开算。
RPS 与 TPS 有什么区别?
中文缩写有时容易混:在 AI API 语境下,RPS = Requests Per Second(每秒完成请求数);TPS = Tokens Per Second(每秒生成Token 数,衡量推理速度)。一个是”每秒多少单”,一个是”每单写多少字的速度”,两个完全不同维度。传统数据库圈的 TPS = Transactions Per Second(和 AI API 没关系,注意区分)。