mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-05 00:47:48 +08:00
56 lines
4.3 KiB
Markdown
56 lines
4.3 KiB
Markdown
# 调度策略级故障转移
|
|||
|
|
|
||
|
|
调度策略的 `default_policy` 支持跨提供商的转移预算与错误规则。它们跟随当前请求的 `routing_execution_policy` 快照进入执行器,不依赖运行中修改全局系统设置。已有策略缺省为不限次数、不限累计时间、无全局错误规则。
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"default_policy": {
|
||
|
|
"sticky_key_attempts": 2,
|
||
|
|
"max_transfer_count": 3,
|
||
|
|
"max_transfer_timeout_seconds": 90,
|
||
|
|
"failover_rules": {
|
||
|
|
"success_failover_patterns": [
|
||
|
|
{ "pattern": "(?i)capacity.*exhausted" }
|
||
|
|
],
|
||
|
|
"error_stop_patterns": [
|
||
|
|
{ "status_codes": [400, 413], "pattern": "invalid.*parameter" },
|
||
|
|
{ "status_codes": [422] }
|
||
|
|
]
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## 预算语义
|
||
|
|
|
||
|
|
- `sticky_key_attempts` 是首个粘性候选上的总尝试次数,`2` 表示首次请求加一次同 Key 重试。该行为保持不变。
|
||
|
|
- 全局 `max_transfer_count` 统计切换候选的次数,首次尝试不计数。同一提供商、端点、Key 上的重试不计数;改变该组合计一次。`3` 最多允许首次候选之后再切换三次。
|
||
|
|
- 全局 `max_transfer_timeout_seconds` 从首次候选开始执行时计时,覆盖后续重试与切换间的累计耗时。它在准备下一次尝试时检查,不会强制打断已经执行中的调用或已提交给客户端的流;单次连接、首字节、读取和非流式完整调用超时仍独立生效。
|
||
|
|
- 两个全局预算的 `0` 都表示不限制。被筛除、禁用或被提供商级预算跳过而未执行的候选不计数。
|
||
|
|
- 提供商自身的转移次数和时间预算继续生效。提供商预算耗尽只跳过该提供商,仍可尝试其他提供商;全局预算耗尽则不再执行任何提供商的新尝试。
|
||
|
|
- 预算仅约束当前请求,不能重置或替代客户端取消策略、权限校验及本地执行异常的终止行为。
|
||
|
|
|
||
|
|
## 错误规则
|
||
|
|
|
||
|
|
先匹配调度策略的全局显式规则;未匹配时继续使用提供商的规则及协议默认行为。本地执行函数真正返回 `Err` 时仍然终止,不做兜底重放。
|
||
|
|
|
||
|
|
- **成功转移规则**:仅当 HTTP 200 响应匹配配置的正则时继续转移,不是对所有 200 进行重试。非流式请求匹配响应体;流式请求只匹配尚未交付业务输出的有界预读取内容。
|
||
|
|
- **错误提前终止**:适用于 400–599 错误。状态码与正则都填写时要求同时满足;只填状态码表示该状态一律终止;只填正则表示在所有错误状态上匹配。流内错误使用解析后的错误状态,而不是外层 200。
|
||
|
|
- **网络错误**:没有上游 HTTP 状态的连接、TLS、DNS、提交前超时等错误统一继续转移;提供商级别若单独配置了停止规则,仍按提供商规则处理。
|
||
|
|
- 正则使用 Rust `regex` 语法,支持 `(?i)` 等内联标志。服务端拒绝无效正则、无意义的空规则以及错误状态范围。每组最多 64 条,每条表达式最多 4096 字节。
|
||
|
|
|
||
|
|
## 流式 200 的恢复窗口
|
||
|
|
|
||
|
|
上游 HTTP 200 响应头不再默认关闭标准文本 SSE 的恢复窗口。执行器先缓冲协议开场事件,例如 Responses 的 `response.created`、Chat 的 role-only 增量、Anthropic 的空 `message_start` / 文本块起始事件。图片专用流保留原来的响应头提交行为,除非显式配置了需要预读取的规则。
|
||
|
|
|
||
|
|
首个业务内容之前的结构化错误、过早 EOF、首字节超时以及 200 正则命中会进入统一故障转移判断。真实文本、思考、工具调用或正常结束事件确定后,缓冲内容按原顺序交付;之后发生的错误保持终止,不重新执行原请求。
|
||
|
|
|
||
|
|
预读取受单次首字节时间和既有字节上限约束。达到字节上限时保守提交,避免无限缓冲;这意味着不能承诺识别响应任意位置的错误或正则。原始 HTTP 状态与最终执行结果是不同观测值,不能因流内失败而伪改已经发送的 HTTP 状态码。
|
||
|
|
|
||
|
|
## 排查
|
||
|
|
|
||
|
|
- `routing_transfer_limit_reached`:当前调度策略的累计次数或时间预算耗尽。
|
||
|
|
- `provider_transfer_limit_reached`:提供商自身的预算耗尽。
|
||
|
|
- `local_stream_candidate_retry_scheduled`:输出前的流内错误或 200 规则触发了继续调度。
|
||
|
|
- `local_stream_transport_retry_scheduled`:输出前传输错误触发了继续调度。
|