先记住这个答案
先根据上游请求数和 Token 等限额估算可持续请求速率,再用该速率乘以平均在途占用时间,得到稳定负载下平均并发的近似值。实际并发上限要留有余量,并结合延迟分布、突发、重试和服务目标压测调整。连接池的物理连接数不总等于业务并发数,HTTP/2 多路复用与 HTTP/1.1 配置不同;流式调用也可能长期占用容量。业务层仍需要独立的并发许可和速率控制,不能靠把连接池开大来突破上游配额。
- 先确定可持续速率,再估算在途工作数量
- 物理连接、业务并发和时间窗口配额分别控制
- 流结束或取消完成后才按实际语义释放资源
把不同配额先换成可比较的速率
假设请求上限是每分钟一百二十次,Token 预算每分钟十八万,每次平均消耗一千五百 Token,两项都对应每秒两次请求。若每次在途平均十五秒,稳定状态平均约三十次在途;保守降低目标速率后再估算并发。
下面只做算术说明,并没有实现限流器。真实提供商可能分别计算输入、输出、缓存或预留 Token,也可能在更短窗口限制突发。必须按实际配额口径和响应信息估算,不能把所有 TPM 都粗暴理解为最终文本长度。
const requestsPerMinute = 120;
const tokensPerMinute = 180000;
const estimatedTokensPerRequest = 1500;
const targetRequestsPerSecond = Math.min(
requestsPerMinute / 60,
tokensPerMinute / estimatedTokensPerRequest / 60
) * 0.8;
const averageSecondsInFlight = 15;
console.log(targetRequestsPerSecond.toFixed(1));
console.log(Math.ceil(targetRequestsPerSecond * averageSecondsInFlight));查看输出与解释
1.6
24算例得到目标速率每秒 1.6 次、平均在途估算 24 次。这不是自动推导出的最优硬上限;请求长度波动、尾延迟和突发分布仍需通过实际观测决定余量。
为什么连接池数量不能直接等同并发许可
HTTP/1.1 下连接复用和流水线配置会影响一条连接承载的请求数,HTTP/2 则可以在一条连接上复用多个流。以 Undici Pool 为例,它管理面向同一上游的客户端实例;具体连接与流限制应按所用版本和协议核对。
业务信号量应覆盖真实请求生命周期。流式接口收到响应头后,模型仍可能持续生成,不能此时就当作请求完成释放全部许可。取消时还要关闭或消费响应体并确认客户端清理语义,否则看似空闲的计数与实际连接占用会越来越不一致。
用分层指标判断到底缺哪种容量
同时观察应用等待许可时间、连接池等待时间、上游响应时间、流持续时间与限流响应。应用队列很长但连接空闲,可能是许可过小;连接等待高而上游配额有余量,才需要评估传输容量;大量限流响应则不应优先增加并发。
多副本共享同一上游账号时,必须按总额分配速率和许可。重试也消耗真实容量,应纳入统计并受总期限约束。调大参数前先检查是否有未关闭的流、过长输出或无法及时取消的调用,否则扩池可能只是把资源泄漏推迟暴露。
容易答错的地方
- 并发等于 RPM 除以六十
- 这个结果是每秒速率,缺少请求占用时长;并发描述同一时刻在途的工作数量,需要结合时间才能估算。
- 把 p99 时长代入公式就得到严格容量保证
- 平均关系不直接保证尾延迟目标,极端分布与突发会改变排队行为;分位数可以辅助保守规划,但仍需实际负载验证。
面试官还会怎么问?
短输出和长输出请求适合用同一个并发值吗?
可以共享总保护,但长度差异很大时应分别估算资源占用并考虑分类调度,否则长流可能长期阻塞短交互请求。
收到 429 后降低连接数就够了吗?
不一定,429 可能来自请求速率、Token 预算或其他限制;应识别实际瓶颈并调整相应控制,连接数只是其中一个传输参数。
用户关闭页面后是否可以立即释放全部资源?
应先传播取消并清理客户端请求。前端连接消失不代表上游生成已经停止,释放和记账需要依据后端实际请求状态。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。