news 2026/9/16 14:35:51

Weave Router 的 dispatch 执行边界完全指南:plan walk、retry/failover 与 attempt 事件流如何运作

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Weave Router 的 dispatch 执行边界完全指南:plan walk、retry/failover 与 attempt 事件流如何运作

Weave Router 的 dispatch 执行边界完全指南:plan walk、retry/failover 与 attempt 事件流如何运作

【免费下载链接】routerModel router for agentic systems. Routes every prompt to the right model in <50ms. Cut costs 40-70% with just an endpoint change.项目地址: https://gitcode.com/GitHub_Trending/router101/router

Weave Router是面向 agentic systems 的模型路由器:它在 50ms 内把每个 prompt 路由到最合适的模型,仅更换一个 endpoint 就能降低 40–70% 的推理成本。而支撑这一能力的"最后一公里",就是 internal/dispatch/ 包——它是策略解析出的执行计划(plan)与各家 provider 适配器之间的唯一执行边界:拿着计划逐个走完候选目标、应用统一的 retry/failover 规则、发出有序可审计的 attempt 事件流。

dispatch 是什么:计划与上游之间唯一的边界

很多路由系统里,"该调哪个上游、失败了怎么办"散落在各个业务包里。Weave Router 的做法是把这一切收拢到dispatch

功能包只依赖抽象的inference.Executor契约,只有 dispatch 包会真正解引用providers.Client去发起上游 I/O。

这条规则不是口头约定,而是有机器检查兜底的——架构基线清单在 docs/INFERENCE_BOUNDARY.md 中冻结了每一个 provider 调用点,make inference-boundary会拒绝任何新增的越界调用。

执行边界由四个部件组成:

部件文件职责
Executorexecutor.go走 plan 的目标序列,应用重试/故障转移规则,发出 attempt 事件
Clients注册表clients.go启动时冻结的只读 provider 客户端注册表
Transport/AttemptFuncexecutor.go#L13-L52单次 attempt 的传输适配器,声明"是否已提交、如何重置、如何准备凭证"
AttemptSinkexecutor.go#L54-L65按序接收 attempt 事件,落盘失败不得阻塞分派

plan walk:Executor 如何一步步走完目标序列

Executor.Run是整条流水线的核心(executor.go#L160-L307)。它的走法非常确定:

  1. 取目标序列plan.SelectedTarget()排第一,随后依次是plan.AlternativeTargets()(策略声明的备选目标);
  2. 预算裁剪:若plan.Budget().MaxAttempts > 0且目标数超出上限,序列会被截断——预算约束的是含同目标重试在内的总 attempt 数
  3. 逐个目标推进:每个目标先向Clients注册表取客户端。若该 provider 在本部署中未配置,则记录一个skipped事件(原因provider_not_configured)并继续走下一个目标,而不是直接失败;
  4. 成功即返回:任何一个 attempt 成功,Result会带上ServedTargetFallbackUsed(是否用了备选目标)和ResponseCommitted,并立即结束 walk。

注册表本身在 clients.go 中定义:NewClients在启动时拷贝provider 映射,之后调用方再修改自己的 map 也不会影响 dispatch 行为;映射到 nil 客户端的名字"算已注册"(可用于资格判断)但永远不可分派。

retry 与 failover:同一目标的两种"救火"方式

这是 dispatch 最有价值的部分——它把"重试"和"故障转移"严格分开,且规则集中在一处:

同目标重试(same-binding retry)

只有同时满足以下条件才会在原地重试:

  • 错误是瞬时的(providers.IsRetryable);
  • 计划里只有一个目标(单目标计划没有别的路可走);
  • 重试次数未超上限MaxSameBindingRetries = 2
  • 重试墙钟预算未耗尽:sameBindingRetryBudget = 10s,防止挂死的上游把每次请求都拖满超时(见 executor.go#L67-L75)。

退避采用指数策略:基础 250ms,每次重试翻倍(250ms → 500ms)。退避睡眠通过sleepWithContext尊重 context 取消。

跨目标故障转移(failover)

多目标计划中,当错误可重试、上游模型不存在(model-not-found)或上游账单被阻断(billing-blocked),且尚未有任何响应字节提交给客户端时,才 failover 到下一个目标(executor.go#L292-L304)。

两个特殊开关由Transport声明,用于覆盖默认规则:

  • Committed:响应已开始流式写给客户端后,重试被永久禁止——再发一次请求对用户毫无意义。此时记录committed失败原因并终止;
  • Terminal:报告"即使错误类别允许重试也必须立即结束"(例如凭证租约拿不到);
  • Bound:操作必须留在当前目标(例如调用方绑定的凭证在提供服务)——瞬时错误可以原地重试,但绝不 failover

失败原因是有界的机器词汇

每个失败 attempt 都会映射到一个有限的失败原因常量(executor.go#L77-L89),事件里永远不携带上游响应体内容

失败原因含义
provider_not_configured该 provider 在本部署未配置
target_mismatch准备出的 wire 请求与计划目标不一致(见下节)
upstream_status/upstream_model_not_found/upstream_billing_blocked上游 HTTP 状态类错误
transport/canceled/committed/prepare/attempt_budget_exhausted传输、取消、已提交、准备阶段失败、预算耗尽

attempt 事件流:每次上游尝试的完整审计线

每一次 attempt(无论成功、失败、跳过还是中止)都会按序写入一个AttemptEvent(契约见 telemetry.go#L59-L77):

  • 定位信息Provenance(Purpose、PolicyID、registry/policy 修订号)+RequestID+OperationID
  • OperationID的意义:同一个请求可能有多次推理操作(主回合 + handover 摘要),它保证不同操作的 attempt 序号永不碰撞;
  • 结果信息AttemptIndex、目标TargetOutcomeserved/failed/skipped/aborted四种之一)、有界的FailureReasonUpstreamStatusCodeLatency

Sink接口只有一条纪律:落盘失败绝不能阻塞分派主流程。事件与请求摘要共享同一份 Provenance,因此事后可以把"这次尝试用了哪个策略版本"跨全部数据源对齐复盘。

防线:如何保证"发给上游的确实是计划指定的模型"

dispatch 还内置了一道 I/O 前检查:GuardTarget包装任意 provider 客户端,在请求真正上线前校验 wire 请求体中的model字段必须等于计划目标的 catalog ID 或 upstream ID(target.go)。不一致则返回ErrTargetMismatch,请求根本不会发出,executor 收到后以target_mismatch原因终止操作——这是"策略说用 A 模型、代码却发了 B 模型"这类事故的硬防线。

Buffered 适配器:摘要类辅助调用的标准姿势

像 handover 摘要、标题生成这类非流式辅助推理,通过dispatch.Buffered接入(buffered.go):Prepare为某个 attempt 的目标构建 wire 请求,Consume解析完整响应。整个响应先被捕获、再交给调用方读取,天然适配 executor 的Committed/Reset语义。

快速导航:继续深入

  • 执行核心:internal/dispatch/executor.go(Run方法即全部 walk/retry/failover 逻辑)
  • 执行契约:internal/inference/executor.go(ResolvedPlanExecutor接口)
  • 事件与结果类型:internal/inference/telemetry.go、internal/inference/outcome.go
  • 调用点冻结清单:docs/INFERENCE_BOUNDARY.md
  • 行为回归测试:internal/dispatch/executor_test.go 与 internal/proxy/baseline_failover_integration_test.go

一句话总结:Weave Router 的 dispatch 把"选谁、试几次、失败怎么办、留下什么记录"这四件事从散落各处的业务代码中抽离出来,变成一条确定、有界、全程留痕的执行边界——这正是它能把路由决策压进 50ms 并稳定交付的原因。

【免费下载链接】routerModel router for agentic systems. Routes every prompt to the right model in <50ms. Cut costs 40-70% with just an endpoint change.项目地址: https://gitcode.com/GitHub_Trending/router101/router

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 14:33:56

SpringBoot酒店管理系统实战:从数据库设计到答辩讲解

简介&#xff1a;这是一份基于SpringBoot构建的酒店管理系统完整项目&#xff0c;面向正在完成课程设计、期末大作业或毕业设计的计算机专业学生&#xff0c;也可作为Java Web实战练手的参考案例。项目曾获导师指导并认可&#xff0c;属于98分的高分作业&#xff0c;涵盖系统源…

作者头像 李华
网站建设 2026/9/16 14:33:47

STM32F407移植NES模拟器:Cortex-M4实战指南

简介&#xff1a;STM32F407移植infoNES是一份将任天堂NES模拟器完整搬到ARM Cortex-M4平台的嵌入式实战工程。资源面向嵌入式开发者、STM32F4初学者及复古游戏爱好者&#xff0c;重点解决在资源受限MCU上实现游戏画面渲染、音频输出、手柄输入与ROM加载的协同调度&#xff0c;并…

作者头像 李华
网站建设 2026/9/16 14:32:10

5分钟配好 FanControl:AMD显卡风扇控制与温度曲线完整教程

5分钟配好 FanControl&#xff1a;AMD显卡风扇控制与温度曲线完整教程 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trendin…

作者头像 李华