并发 Agent 共享同一个限流端点时,无协调的并行执行会导致大量请求在超时后才失败。HiveMind 的实测数据显示,3/11 个并行 Agent 因连接重置和 502 错误而崩溃,失败率 27%。而在无协调场景下,失败率高达 72-100%。问题的根源不是容量不足,而是请求到达时间与执行时间的不匹配——大量请求同时涌入,每个都在等同一个被限流的端点,最终在超时后才失败,白白消耗了客户端资源和上游配额。
本文记录我在网关层做请求排队和 SLA 感知准入控制的实现思路。测试用 4stoken.cn 的兼容端点做并发压测,因为它能同时路由到多个上游,方便在同一个环境里观察不同上游的限流行为。本文为工程记录,不构成选型建议。
为什么普通限流不够
大多数网关的限流是计数器式的:每秒允许 N 个请求,超出就 429。但 LLM 请求的执行时间差异极大——短请求 200ms 返回,长请求可能跑 30 秒。计数器式限流只看请求数量,不看每个请求占用连接的时间,结果是:N 个长请求同时进来,全部占着连接,后续请求即使在额度内也拿不到资源。
更糟的是,客户端收到 429 后的典型行为是立即重试。重试请求和正常请求混在一起,进一步推高并发。最终上游开始返回 502,客户端继续重试,形成正反馈,整个链路雪崩。
OS 启发的调度原语
解决思路是把操作系统进程调度里的概念搬到网关层。HiveMind 的调度器参考了这些原语:
准入控制。 请求进入队列前先做一次判断:当前并发数是否超过安全上限?如果超过,是排队还是直接拒绝?这里的关键是安全上限不能是固定值,要根据上游的实际响应动态调整。
限流追踪。 记录每个上游的实时状态:当前并发数、最近一分钟的错误率、P95 延迟。这些数据是后续调度决策的输入。
AIMD 背压。 借鉴 TCP 的加法增加乘法减少策略:延迟健康时逐步提高并发上限,延迟恶化时快速降低。不需要手动调参,系统自己找平衡点。
Token 预算管理。 不只是限制请求数,还要限制总 Token 消耗。一个长上下文请求可能占用一个短请求 100 倍的 Token 配额。
优先级队列。 请求分高、中、低三级。高优先级请求(付费用户、实时交互)优先调度,低优先级请求(批处理、后台任务)可以等待。
SLA 感知的准入控制
核心改进在于:请求进入队列前,先预测完成时间。如果预测完成时间超过客户端 deadline,立即返回 429 并附带 retry hint,而不是让请求进入队列、等待、最终超时。
预测模型可以很简单:用当前队列长度乘以平均执行时间,加上请求自身的预估执行时间。如果总和超过 deadline,直接拒绝。
defshould_admit(request,queue,deadline_ms):avg_exec=queue.stats.avg_execution_time estimated_wait=len(queue)*avg_exec estimated_total=estimated_wait+request.estimated_execution_timeifestimated_total>deadline_ms:retry_after=int(estimated_total/1000)returnFalse,retry_afterreturnTrue,0这个逻辑的价值在于:快速失败比慢速失败好。 客户端在 100ms 内拿到 429 和 retry hint,可以立即做其他事或等待指定时间后重试。而如果请求进入队列,等 10 秒后才超时,客户端不仅浪费了 10 秒,还可能已经重试了多次。
优先级调度与反饥饿
高优先级请求先调度,但低优先级请求不能无限等待。做法是等待时间越长,有效优先级越高。实现上可以用一个简单的公式:effective_priority = base_priority + wait_time / aging_factor。
这样低优先级请求在等待一段时间后,有效优先级会追上高优先级请求,避免被永久阻塞。高优先级请求在系统空闲时立即调度,在系统繁忙时也只需要等待有限时间。
AIMD 自适应并发
固定并发上限的问题是:设高了会过载,设低了浪费容量。AIMD 的做法是动态调整:
· 每次请求成功,并发上限加 1(加法增加)
· 每次请求超时或失败,并发上限乘以 0.5(乘法减少)
这个策略在 TCP 拥塞控制里被验证了几十年,搬到网关层同样有效。实测中,AIMD 能在 30 秒内从冷启动找到稳定的并发上限,并且在流量突增时快速降级避免雪崩。
反直觉的发现:透明重试 > 准入控制
HiveMind 的消融实验显示了一个反直觉的结论:透明重试是降低失败率最关键的调度原语,而不是准入控制。
透明重试的机制是:网关收到上游 429 或 502 后,不立即返回给客户端,而是在网关内部按退避策略重试,对客户端完全透明。客户端感知不到重试,也就不会触发客户端的重试逻辑。
这个机制之所以有效,是因为大多数上游错误是瞬时的——上游负载均衡切换、某个实例短暂过载、网络抖动。透明重试吸收这些瞬时错误,客户端看到的成功率显著提升。而准入控制虽然能防止过载,但如果上游已经返回了错误,准入控制无法补救。
两者是互补的:准入控制防止系统进入过载状态,透明重试处理已经发生的瞬时错误。
结论
LLM 网关的请求调度不是简单的计数器限流能解决的。核心原则有三条:
第一,快速失败优于慢速失败。 SLA 感知的准入控制让客户端在 100ms 内拿到明确的 retry hint,而不是等 10 秒后超时。
第二,并发上限应该动态调整。 AIMD 背压不需要手动调参,能在 30 秒内找到平衡点。
第三,透明重试是最大的单点收益。 网关内部重试比客户端重试更有效,因为客户端重试会放大并发,而网关重试可以精确控制退避策略。
在 4stoken.cn 上跑并发压测时,能直观看到无调度和有 AIMD 准入的失败率差异。这套调度逻辑对所有多上游网关通用,4stoken.cn 在这里只作为测试环境,方便观察多上游并发行为。