← 返回题目列表

多个 Agent 任务如何排队与调度?

高频 困难 第 19 / 26 题 更新于 2026/09/17
AI Agent任务队列调度并发控制

简化版

Agent 任务调度要把长任务拆成可恢复作业,通过持久化队列实现削峰、重试和水平扩展。调度器综合优先级、截止时间、租户公平、模型与工具配额、任务依赖和预估成本选任务;worker 用租约领取,心跳续租,完成后幂等提交。不能只用一个 FIFO 队列,否则长任务会阻塞短任务,高并发租户也会挤占所有容量。

详细版

任务记录至少包含类型、租户、优先级、创建时间、deadline、依赖、所需资源、预算、重试次数和幂等键。入队前做准入控制;调度时先过滤依赖未满足和资源不可用任务,再按加权公平或优先级选择。CPU 沙箱、浏览器、GPU 模型调用应分资源池限流,防止某一种任务拖垮全部系统。

submit -> admission -> ready queue -> lease -> worker
                    ^                 |
                    | retry/backoff <-+
                    + dependency wakeup

队列通常只能保证至少一次投递,因此执行必须幂等。worker 崩溃后租约到期重新投递;有副作用的工具使用业务幂等键。监控排队时间、运行时间、租约超时、重试放大、各租户份额和 deadline miss,并为毒任务设置死信队列和人工处置。

完整版教学

一、为什么 Agent 需要异步队列

Agent 任务可能持续几分钟,期间还会等待模型、浏览器、代码沙箱或人工审批。若 HTTP 请求一直占住进程,客户端断开会丢失状态,流量突发也会直接压垮下游。

持久化队列把接收与执行解耦:入口快速校验并返回任务 ID,worker 按容量消费;暂时无资源时任务仍安全排队。队列还提供重试和水平扩展,但不会自动解决公平、幂等与副作用问题。

记忆钩子:队列解决“什么时候轮到执行”,状态机解决“执行到哪里”,幂等解决“重复执行会不会出事”。

二、任务元数据决定能否正确调度

只存 Prompt 和创建时间,调度器只能做 FIFO。生产任务要声明租户、任务类型、优先级、deadline、预计成本、所需工具、依赖任务和数据地域,才能做资源匹配和隔离。

字段调度用途
tenant_id公平份额与配额
priority / deadline紧急程度
resource_class匹配 GPU、浏览器或沙箱
estimated_cost准入与装箱
dependencies未满足时保持阻塞
idempotency_key去重与安全重放

预计值可能不准,因此执行中要更新实际 token、时长和资源使用,让后续估计逐渐校准。

三、FIFO 会产生队头阻塞

假设队首是一个需要 10 分钟的浏览器任务,后面有 100 个各需 1 秒的分类任务;单 worker FIFO 会让所有短任务至少等 10 分钟。按任务类型建立资源池,或采用短作业优先,可以显著降低平均等待时间。

但短作业优先可能让长任务长期饥饿,所以常加入 aging:等待越久,动态优先级越高。一个简单公式是:

effective_priority = base_priority + waiting_minutes × 0.1

系数需根据 SLA 调整。紧急优先级也要受权限控制,不能让所有调用方都标最高级。

四、多租户需要加权公平

若租户 A 瞬间提交一万条任务,纯全局优先队列可能让租户 B 的十条任务一直等待。可为租户设置并发上限、速率和权重,使用加权轮询或 deficit round robin 分配服务份额。

例如总并发 20,A 权重 3、B 权重 1,在双方都有积压时可近似分配 15 和 5;B 空闲时,A 可以借用剩余槽位。借用提高利用率,但 B 新任务到达后要能及时收回份额。

公平不只是请求数公平。一次 50K token 的任务与一次 200 token 分类消耗不同,配额可按估计 GPU 秒或成本计量。

五、资源感知调度避免互相拖垮

Agent 的不同步骤消耗不同资源:LLM 受模型限流,网页工具受浏览器实例数约束,代码执行受 CPU 和内存约束。统一并发计数会让大量轻任务占满重资源槽位,或让浏览器雪崩影响纯模型任务。

调度器先做资格过滤:所需资源、地域、模型版本和权限必须可用,再在候选中排序。任务也可在步骤边界释放资源,等待工具时不占用 GPU 令牌。

对下游使用 semaphore 或令牌桶控制并发,并根据 429、延迟和错误率自适应收缩,而不是不断加 worker 把压力推给依赖服务。

六、租约比“取出即删除”安全

worker 领取任务后,队列给它一个 60 秒租约,任务暂时不可见;worker 每 20 秒心跳续租。成功提交后确认删除;若进程崩溃,租约到期,任务重新可见。

READY -> LEASED(worker-7, until=10:01)
       -> ACKED
       -> lease expired -> READY

租约造成至少一次投递:原 worker 可能执行成功却没来得及 ACK,新 worker 会再拿一次。因此工具调用与结果提交必须幂等,不能指望队列“绝不重复”。

七、重试、退避与死信队列

瞬态超时可以指数退避并加随机抖动,参数错误和权限拒绝则应立即失败。若所有失败都立刻重试,大面积上游故障会形成重试风暴。

假设 1000 个任务同时失败,每个立即重试 3 次,下游瞬间看到额外 3000 请求。若按 1、2、4 秒退避并加入随机抖动,峰值会被摊开,但根因未恢复时仍需熔断。

超过最大次数或不可恢复的任务进入死信队列,保留错误分类、状态快照和副作用记录。修复根因后应选择性重放,并继续沿用原幂等键。

八、依赖、取消和优先级变化

DAG 任务的子节点只有在所有必要依赖成功后才进入 ready;上游失败时,下游应阻塞、跳过或走补偿分支,具体由边的语义决定。调度器不能通过轮询全文反复检查,可由状态事件唤醒依赖节点。

排队任务取消较简单,运行中取消则需要协作式信号和安全检查点。有副作用的步骤不能粗暴杀进程后假装未执行。用户提升优先级时,也要防止绕过租户配额与审批规则。

deadline 任务若已经不可能按时完成,继续消耗资源可能毫无价值。准入器可根据预计排队加运行时间提前拒绝,并返回可解释原因。

九、常见误区与追问

  • 误区:有消息队列就自然实现公平调度。 普通 FIFO 不理解租户、资源、deadline 和任务成本。
  • 误区:任务从队列取出后只会执行一次。 租约超时和 ACK 丢失都会重复投递。
  • 误区:增加 worker 总能提升吞吐。 下游模型和工具有限流,盲目扩容会制造拥塞。
  • 误区:最高优先级永远先执行。 需要 aging、公平份额和优先级权限,避免低优先任务饥饿。
  • 误区:重试只要设置三次即可。 要按错误类型、退避、熔断和幂等共同设计。
  • 追问:如何避免长任务阻塞短任务? 分资源队列、预估时长、步骤级让出和 aging 组合使用。
  • 追问:worker 崩溃怎样恢复? 租约过期重新投递,从持久化检查点继续,并依靠幂等保护副作用。
  • 追问:哪些指标最重要? 分租户的排队时间、deadline miss、资源利用率、租约超时和重试放大率。

十、加强记忆

Agent 调度记住“准入、匹配、公平、租约、幂等”:入口根据预算和 deadline 决定能否接单;调度器按依赖和资源匹配 worker,用优先级加 aging、租户权重维持公平;worker 通过租约领取并从检查点执行,超时会再次投递,所以所有副作用必须幂等。错误分类后退避重试,毒任务进死信队列,指标则按租户和资源池观察排队与长尾。