推理服务跟普通微服务最大的区别,是单个请求要占 GPU 好几秒。过载时它不是慢慢变慢,而是把最贵的算力花在注定作废的请求上。拿一个 8 卡实例举例:单请求 2 秒 GPU 时间,理论吞吐 4 QPS。流量涨到 8 QPS,队列深度每秒净增 4,几十秒后排在后面的请求等待时间早就超过客户端能容忍的阈值。它们没有被拒绝,还占着队列位和预分配的资源,GPU 满转,有效吞吐停在原地。
阿里云开发者社区那篇《推理服务的过载保护:排队、降级与熔断的次序》把这个现象说得很直接:推理过载的核心矛盾是“算最贵的资源,算注定作废的请求”。它讲的四层保护里,我认为最容易被忽略、但性价比最高的是第二层——队列超时淘汰。原因不在算法复杂度,而在心理上没人愿意主动砍自己的请求。
大家都在等客户端先放弃
这里的“批内”不只是指 batch 内部,而是指一段排队窗口里的所有请求。大多数服务端设计是“来了就入队”,出队的唯一路径是被执行或客户端断开。这条路径在同步推理里看似合理,实际上把判断责任推给了客户端。
问题在于,客户端早就先放弃了。同步 HTTP 连接在推理耗时长时超时率会陡然上升,阿里云 PAI 的异步推理材料里提到一个数据:推理耗时超过 15 秒时,同步请求超时率增至 62%。这意味着大量请求是“客户端已经断了,服务端还在算”。按原文的估算,排队 80 秒的请求,99% 的客户端早已放弃。
所以超时淘汰做的事很简单:请求在队列里待超过 N 秒(比如 30s),服务端主动把它从队里摘出来,返回 429,不等客户端发现。这层单独能把过载期的有效吞吐提升 25%左右。数字看起来不大,但要意识到,它提升的不是总量,而是在低质量请求淹进来时保住的可用吞吐。省下来的 GPU 时间直接分给了还能被用到结果的请求。
关键在“主动出队”这三个字
这里有个常见实现错误:超时检查只在出队时做。请求一直在队里排到要执行的那一刻,才发现它已经超时,撤销执行,回 429。这个顺序等于是发现浪费之后再止损,但排队期间它一直蚕食调度器的时间和排队位置。要做到真正有效,淘汰线程或者每个消费循环都必须周期性扫队头到队中,按入队时间戳主动剔出。
更细的一点是淘汰判断要和客户端 timeout 对齐,不一致会带来两种浪费。服务端设 30s,客户端设 60s,那么 35 秒时你淘汰了一个还能用的请求,用户看到的是 429,但他自己不认为这一轮应该失败。反过来,服务端设 60s,客户端设 30s,60 秒内正常排队的大量请求早就没人要了。合理的设置是按你的 P99 排队时间加一点余量取,并结合交互请求和批量请求拆桶。
不是所有渠道都该用同一个 N
推荐系统的特征拼装请求和后台批量生成,在排队超时上不该用一样的时间。交互请求(在线问答、实时补全)用户是真的在等,它的淘汰线应该紧贴客户端可忍受时间;批量请求(离线打标、后台摘要、队列里刷的合成任务)本身没有人在看进度条,淘汰线可以放很长,甚至不参与淘汰,只需要有容量上限。
这跟原文放到队列一层里讲的也是同一件事:入口限流应该按交互、批量分桶,过载时先砍批量桶。队列淘汰也要遵循同一组标签。只要不区分,就不受控地让批量流量混在交互请求队列的前后顺序里,结果可能是交互流量虽然在,但碰到前面一大段长时批请求(批量与交互混排),交互 P95 抖到不可用。给不同桶不同的淘汰线并切换不同的完成返回策略,反而是更贴近成本现实的取舍。
配额、迟到响应与恢复时的二次冲击
实现主动失效一项也要在服务层留可观测信息。从工程落地角度有几个点必须提前想清楚:
- 408/429 选择:淘汰根因是服务端放弃,不是一个客户自己的超时,所以返回更准确的应该是带 Retry-After 的 429,也便于客户端触发退避而不是判定请求错误。
- 重试引发补偿流。进入优雅退潮时,原请求返回 429 之后很多客户端会重试。把 retry 延迟和 jitter 控制好,否则淘汰做得越狠,重试进来的吞吐越猛。Jitter 应该跟排队优先级一起设计:对于批量任务可用较长的退避,并加到前面去,不要在还没退役完成时把它拉起来。
- 恢复不要靠一次性升档。原文的恢复节奏是限流阈值分档上(比如 50%、80%、100% 每档观察两分钟,降到一半后每两分钟重争查一遍信号),讲得很清楚了:队列清空的瞬间恰是补偿突发出现的时候。淘汰率指标可以辅助你判断,如果你在这里就立刻把限流回到全量,补一针重试的流量极可能把排队时间直接打回淘汰线。
最后是那三个最值的监控位:队列深度、请求等待的 P95 以及超时淘汰率。淘汰率最实用。它是一个开销小但解释力很强的资源分配效果信号。淘汰率长期在 5% 以上,说明限流或淘汰线比较松懈,需要收紧;到 20% 左右就不能开,或按业务目标放行,反而应该补容量。
横向看其他实现
淘汰并不是队列范式的唯一做法。PAI 的异步推理用独立的输入/输出队列和订阅窗口大小来做背压,推理实例按自身能承受的并发度订阅,队列服务会记录实例连接;如果实例失联,它把分发给该实例的请求重新推到其他实例。它不淘汰请求,代价是需要客户端接受异步检索结果的语义,工程链更长(消息队列、输出队列、扩展也需要观察)。GKE 批推理那一侧更外围:订阅端延长 Pub/Sub 的确认窗口、用死信主题装住毒丸消息、遇到 429 退避消费。它们主要保住消息不丢,不解决排队里的死等。两者都与“批内超时淘汰”互补,而非替代。
超时淘汰真正的成本,主要不在代码量,而在你需要甘愿在每个过载周期做一轮“从队列里剔除请求”的决策:你知道那些请求如果继续排着还有极小概率成功,但还是主动放手,将剩余 GPU 时间留给排队更短、更可能被拿到结果的请求。这个取舍必须先在监控面板和压测里测清楚,再上线固化淘汰线,不能到最后变成排障时反复猜测随机参数。
转载请注明出处: 皮哈皮阿
本文的链接地址: https://blog.phpat.com/ai-dev/640.html
微信或手机浏览器扫一扫,随时随地随心阅读与分享
-
上下文工程:从 Prompt 到 Context 的工程化实践
客服 Agent 答错时,团队第一反应是换模型。把那次请求的上下文打印出来才发现,模型看到的是一份过期政策、两份互相矛盾的条款,还有一长串无关日志。上下文工程要解决的,就是这类问题。
2026/10/06
-
RAG 的下一站:Agentic Retrieval
用户问“我们去年买的套餐现在还能退吗”,经典 RAG 检索出一段通用退款政策就结束了。可这个问题至少要拆成订单时间、地区、套餐版本三件事。Agentic Retrieval 要解决的,就是这种“一次检索不够用”的场景。
2026/10/12
-
Agent 上下文压缩:四层策略与失败代价
把 Claude Code 的四段分层与 Hermes Agent 的双阈值压缩系统并排看重:200K 窗口下的 50%/85%、legacy 与 lean 尾部的实测差池、未处理到的摘要模型窗口溢出,以及工具对配对边界为什么是能不能跑的问题。
2026/10/23
-
约束解码让 JSON 不再崩,但它会改坏推理
约束解码让 JSON 解析失败率归零,工程师可以删掉一堆重试和修复代码。但它会挤占模型的推理预算:强制格式在部分任务上带来10%以上的准确率下降。文章梳理 OpenAI、Anthropic、Gemini 和其他自托管引擎的现状,以及 schema 设计、两阶段模式与编译缓存几个实操要点。
2026/10/22
-
推理模型输出被截断后怎么接回去
推理模型遇到输出截断,重试整条请求代价高;续写也有隐藏门槛。从识别边界、提示回灌到 prefill 与成本判断,聊聊工程上怎么做才不算亏。
6天前
-
推理模型的并行思维链采样怎么用才不亏
并行思维链采样的成本不是白花的。结合推理模型测试时计算的几条实证结论,梳理best-of-N、束搜索、自洽性投票和自我修订在什么场景下划算、什么场景下只是在烧钱。
5天前
京公网安备11011402053654 
@muffin:链接已更新,分类图像功能...
AI网址导航模版图标库更换指南
作者大大,图标库邀请链接失效了,麻烦更新...
AI网址导航模版图标库更换指南
太好看了,快点更新!
友情链接
@戴墨镜的刘备:哈喽,路过点赞。
vue.js组件之手写签名板vue-signature-simple
太好看了,快点更新!太棒了!👍真的很赞!
vue.js组件之手写签名板vue-signature-simple
你写得非常清晰明了,让我很容易理解你的观...
Emlog插件RSS订阅器发布