报错是这么冒出来的。推理服务支持 128k 上下文,平时 8 并发很稳,某次批量文档摘要同时进来 8 个 12 万 token 的请求,显存瞬间打满,服务进入 CUDA OOM 后整体不可用。
中间走过弯路,把「调度器先到先服务,长请求把短请求挤在后面」当成主因,改完现象没变。
把日志和配置对完,能解释这个现象的基本就这几处。KV cache 随上下文线性增长,长请求吃满预留空间。另一种情况是并发控制按请求数算而没有按 token 预算算。
还有一种情况,没有为超长请求设置单独的队列与上限。
算单个长请求的 KV 占用
python -c "print('kv bytes = 2*32*128000*4096*2')"
再往下按 token 预算做准入而不是按请求数
python -c "print('budget 200000 tokens, reject if queued_tokens + req > budget')"
然后把超长请求路由到单独实例池
python -c "print('route ctx>32k to pool-long, max_num_seqs=2')"
压测验证长请求涌入时短请求仍可用
python bench.py --mix long:8,short:200 --duration 300
恢复的判定其实很直接。长请求被路由到独立池后,主池在长文突增时仍保持 200ms 内的首 token 延迟,OOM 未再出现,队列拒绝率 1.3%。
容易忽略的是,长上下文的成本是显存而不是 QPS,并发限流要按 token 预算算,按请求数限流在长文场景等于没有限制。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。
