OpenRouter 详解可靠性与自动故障转移:请求如何持续成功
OpenRouter Reliability & Automatic Failover: How Requests Keep Succeeding
OpenRouter 发布可靠性机制详解:请求失败时通过两层配置保持成功,provider-layer failover 默认开启,在同一模型的不同供应商间切换;model fallbacks 通过 models 数组按优先级跨模型兜底,需主动配置。
官方详解两层故障转移机制与计费例外,读者可据此配置生产环境的 LLM 请求可靠性。
直接调用单一提供商意味着单点故障。当它宕机时,你的用户会看到错误,而你一小时后才从支持工单中得知。这正是 OpenRouter 解决的问题:它会路由每个请求以保持其成功,自动跨提供商,并在配置后跨模型。
使用 OpenRouter,你可以通过 2 个独立的配置为应用构建可靠性。提供商故障转移是自动的,默认开启。模型回退是可选加入的。
这 2 层覆盖不同的故障;如果主模型的所有提供商同时失败,提供商故障转移就无处可去。模型回退是第二道防线。
这是一个值得在每个项目中作为起点的配置。复制并调整:
from openrouter import OpenRouter
client = OpenRouter(api_key="<OPENROUTER_API_KEY>")
completion = client.chat.send(
model="anthropic/claude-sonnet-4.6",
models=["openai/gpt-5.4-mini"], # fallback if the primary fails
messages=[{"role": "user", "content": "Summarize this incident report."}],
)简而言之
- LLM 请求失败的原因是可预测的:提供商中断、速率限制(429)、上下文长度错误和内容审核拒绝。
- 可靠性分为 2 层:提供商层故障转移(默认开启,在单个模型内恢复)和模型层回退(通过
models数组可选加入,跨模型恢复)。 - 路由层实时检测提供商健康状况并绕过中断,因此最坏情况下的正常运行时间优于你直接集成的任何单一提供商。
- 故障转移按顺序遍历你的
models列表。一旦列表耗尽,最后一个错误会返回,因此请将可靠的兜底模型放在最后。 - 你不需要为最终失败的请求付费,但用户报告了一些边缘情况(某些 429 路径、部分输出)仍会消耗额度,因此请关注你的活动日志并设置支出限额。
- 使用
only/ignore/order限制提供商会以可靠性换取控制权:候选集越窄,回退选项就越少。
为什么 LLM API 请求会失败?
提供商中断、速率限制(429)、上下文长度验证错误和内容审核拒绝是 LLM 请求失败的可预测原因。单一的直接提供商集成对其中任何一种都没有恢复路径,因此每一种都会变成面向用户的错误。
最简单的例子是速率限制。你直接调用一个提供商,触及其每分钟上限,你唯一的选择是退避、排队或失败。这些都无法帮助盯着加载动画的用户。
社区将路由层称为“AI 的 DNS”是有原因的:它之所以能保持运行,是因为它有不止一个地方可以发送请求。
这 4 种故障模式中的每一种都对应 OpenRouter 中的特定恢复层,了解哪一层处理什么,是你正确配置可靠性的关键。
4 种故障模式,映射到恢复层
以下是会失败的情况,以及 OpenRouter 的哪一层可以恢复它。
| 故障模式 | 表现 | 恢复方式 |
|---|---|---|
| 提供商中断 / 宕机 | 5xx、超时、连接断开 | 提供商层故障转移(下一个提供商) |
| 速率限制(429) | 来自提供商的“请求过多” | 提供商层故障转移,然后模型回退 |
| 上下文长度错误 | 提示超出模型的窗口 | 模型层回退(尝试更大上下文的模型) |
| 审核拒绝 | 被过滤的模型拒绝回复 | 模型层回退(尝试未过滤的模型) |
前 2 个是基础设施问题,第二个提供商可以解决。后 2 个是模型问题,第二个模型可以解决。
在 OpenRouter 上,失败的请求需要付费吗?
简短回答:不需要。当请求在故障转移耗尽后最终失败时,你不会被计费;你只需为成功的运行付费(零完成保险)。
这让重试的设计成本很低:一条回退链在成功前消耗 3 个提供商,也只算你一次成功完成。你可以大胆使用回退,而无需为每一次失败的尝试盯着计费表。
你应该预料到的例外情况
现实世界中存在边缘情况,我们更希望你在这里读到它们,而不是从账单面板上发现。一些用户报告过错误 429 消耗了额度,或者尽管出错但部分输出仍被计费的情况。所以政策是“只为成功运行付费”,但少数 429 路径和部分输出还是漏了过去。
诚实的权衡:零完成保险是真实存在的,但并非无懈可击。检查你的活动日志以确认你被收取了哪些费用,并设置硬性支出限额,这样边缘情况就不会累积出账单。设计时要带上支出上限,而不是假设每个失败的请求都是免费的。
提供商故障转移 vs 模型回退
OpenRouter 在两个不同的层面从故障中恢复。提供商层故障转移是自动的,默认开启;模型层回退是通过 models 数组选择加入的。一个让单个模型在不同提供商之间保持存活,另一个则完全切换到不同的模型。
OpenRouter 会自动在提供商之间进行故障转移,你可以通过 ignore、only 和 order 来塑造候选集。常见情况下你不需要编写重试逻辑。
ignore 按 slug 屏蔽特定提供商。only 限制为允许列表。order 设置明确的先尝试此提供商的顺序。
这 3 个都会缩小候选集,所以要谨慎使用;符合条件的提供商越少,回退选项就越少。
| 提供商层故障转移 | 模型层回退 | |
|---|---|---|
| 恢复的内容 | 为你的模型提供服务的提供商出现故障或 429 | 整个模型不可用,加上上下文长度和审核拒绝 |
| 默认 | 开启(allow_fallbacks: true) | 关闭,直到你设置 models 数组 |
| 控制它的配置 | allow_fallbacks、order、only、ignore | models 数组(优先级顺序) |
| 恢复范围 | 同一模型,不同提供商 | 完全不同的模型 |

这是静态视图。下面的图表展示了运行时实际发生的情况:单个请求如何穿过这两层,以及在哪里以成功或最终错误退出。

提供商层故障转移:一个模型,多个提供商
像 Claude Sonnet 4.6 这样的单个模型通常由多个提供商提供服务。如果 OpenRouter 选择的提供商返回 5xx 或限流,它会自动为同一模型尝试下一个提供商。这由 allow_fallbacks 控制,默认值为 true(提供商选择文档)。
零配置。你一发送请求就能获得这个。
模型层回退:当整个模型不可用时
如果你主模型的每个提供商都失败了,提供商层故障转移就无处可去了。这时 models 数组就接管了:OpenRouter 会移动到列表中的下一个模型(模型回退文档)。这一层是选择加入的,因为它改变了由哪个模型来回答,这是只有你才能做的决定。
上下文长度错误或审核拒绝也会触发这一层,因为这些问题不是换个提供商就能解决的。
这两层协同工作,但它们在幕后以不同的方式工作。提供商层故障转移无需设置即可自动运行。以下是它对每个请求实际做的事情。
提供商层故障转移如何保持一个模型持续运行
对于每个模型,OpenRouter 会在多个提供商之间进行负载均衡,以最大化正常运行时间,使用公开的 3 步规则:优先选择过去 30 秒内没有重大故障的提供商,按价格平方的倒数加权选择成本最低的稳定候选者,其余作为后备(提供商选择文档)。这首先是一种可靠性机制,其次才是成本机制。
实际上,任何在过去 30 秒内出错的提供商都会掉到队尾,而在稳定的提供商中,最便宜的会首先被选中,概率大致与价格差的平方成反比。可靠性优先,成本其次,自动执行。
30 秒的故障窗口是对正常运行时间至关重要的部分。在过去半分钟内出现问题的提供商会自动从前排掉出,无需你采取任何操作。
解读负载均衡的数学原理
文档中的示例展示了可靠性和成本如何协同工作。假设提供商 A 的成本为 $1/M tokens,提供商 B 为 $2/M,提供商 C 为 $3/M,而 B 最近出现了一些故障。
OpenRouter 首先路由到 A,并且由于平方反比加权(1/3² = 1/9),A 被尝试的概率大约是 C 的 9 倍。如果 A 失败,下一个是 C。最近不稳定的 B 最后被尝试:故障历史将不可靠的提供商推到后面,但不会将其排除。

这是默认行为。但如果你已经知道某个提供商不好,你不必等待路由数学来发现这一点。
控制候选集
你可以塑造哪些提供商有资格,这就是你屏蔽不可靠提供商的方式:
order:按显式顺序尝试提供商,例如order: ["anthropic", "together"]。only:请求的提供商 slug 允许列表。ignore:阻止列表,例如provider: { ignore: ["deepinfra"] }以跳过你发现提供过度量化模型的端点。allow_fallbacks: false:硬性停止到你选择的提供商,没有自动备份。
诚实的权衡:使用 only、ignore 或 order 缩小范围“可能会显著减少后备选项并限制请求恢复”(提供商选择文档,原文引用)。你排除的每个提供商都是少一个恢复的地方。限制池子为你带来控制,却牺牲了可靠性,所以要有意地修剪。
在不丢失池子的情况下限制最坏情况延迟
如果你需要可预测的延迟,设置 preferred_max_latency 或 preferred_min_throughput,并在滚动 5 分钟窗口内使用百分位截止值(提供商选择文档)。未达到阈值的端点会被降低优先级,而不是被排除。以下是它与 ignore 结合时的样子:
completion = client.chat.send(
model="deepseek/deepseek-v4-flash",
provider={
"preferred_max_latency": {"p90": 3}, # prefer <3s for 90% of requests
"ignore": ["deepinfra"], # skip a known-bad endpoint
},
messages=[{"role": "user", "content": "Classify this ticket."}],
)以上所有内容都保持一个模型在多个提供商之间存活。但如果该模型的所有提供商都宕机,提供商故障转移就无处可去了。
模型后备会接管并尝试你列表中的下一个模型。它们是协同工作的顺序层,而 models 数组就是开启第二层的方式。
如何设置模型后备
按优先级顺序传递一个 models 数组,如果第一个模型的提供商全部出错,OpenRouter 会尝试下一个模型(模型后备文档)。一个数组,无需重试代码。OpenRouter SDK 将 models 作为一等字段;使用 OpenAI SDK 时,你通过 extra_body 传递它。
cURL:
curl https://openrouter.ai/api/v1/chat/completions \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"models": ["anthropic/claude-sonnet-4.6", "openai/gpt-5.4-mini"],
"messages": [{"role": "user", "content": "Draft a release note."}]
}'TypeScript:
import { OpenRouter } from '@openrouter/sdk';
const openRouter = new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY });
const completion = await openRouter.chat.send({
models: ['anthropic/claude-sonnet-4.6', 'openai/gpt-5.4-mini'],
messages: [{ role: 'user', content: 'Draft a release note.' }],
});完整的触发列表
理解什么会触发后备比知道它存在更重要。以下 4 个条件中的任何一个都可以触发它,直接来自 模型后备文档:
| 触发条件 | 含义 | 哪一层恢复它 |
|---|---|---|
| 宕机 | 提供商不可达或返回 5xx | 提供商层,然后是模型层 |
| 速率限制 | 提供商返回 429 | 提供商层,然后是模型层 |
| 上下文长度校验错误 | 你的提示词超出了模型的窗口 | 模型层(换用上下文窗口更大的模型) |
| 内容审核标记 | 被过滤的模型拒绝回复 | 模型层(换用未过滤的模型) |
计费跟随实际应答的模型,并在响应的 model 字段中返回。请检查该字段以确认是哪个模型处理了请求,尤其是在触发了回退时。
触发列表说明了回退何时启动,但它没有告诉你回退何时停止。
只有撞上才会知道的限制
回退在你的列表末尾停止。“如果回退模型宕机或返回错误,OpenRouter 将返回该错误”(模型回退文档)。它会按顺序遍历你的 models 数组一次,绝不会形成无限重试链。
当失败不属于 OpenRouter 归类为可回退的错误时,回退也不会触发(例如,格式错误请求返回的 400 会直接返回)。
实际的解决办法是排列你的 models 数组,让最后一项是你最可靠的基础模型,即当前面所有模型都失败时你仍信任它能作答的那个。
OpenRouter 如何实时绕开故障
OpenRouter 持续监控所有提供商和路由的响应时间、错误率和可用性,并基于这些实时反馈进行路由(正常运行时间优化文档)。你无需自建监控即可获得自动的提供商健康检测,这是企业评估者最先问到的可靠性功能。这些实时数据支撑着 30 秒故障窗口:正在退化的提供商会立即被绕开,无需等待状态页面更新。
可验证的公开正常运行时间
文档中嵌入了 Claude Sonnet 4.6 和 GLM 5.1 等模型的实时正常运行时间组件,因此提供商可用性是你能够亲眼观察的,而非仅凭信任(正常运行时间优化文档)。有 3 个信号影响路由决策:
- 响应时间会将慢速端点降级。
- 错误率会将返回 5xx 的提供商从前排剔除。
- 可用性驱动 30 秒故障窗口。
如果你正在为生产环境评估这一点,这就是你的答案:实时健康路由、30 秒故障窗口,以及可实际验证的按模型公开正常运行时间,而不是幻灯片上的一个可用性百分比。
平台健康与路由健康
按提供商的路由健康负责实时引导单个请求。平台级健康,即网关本身,位于 status.openrouter.ai。
监控状态页面以了解影响整个网关的事件;信任实时路由自行处理单个不稳定的提供商。
OpenRouter 自动处理路由健康。网关本身则需要你来监控。但故障转移不覆盖哪些情况?
故障转移不覆盖的情况
故障转移能从提供商和模型错误中恢复,这就是边界。它不会无限重试,不会捕获非错误的坏响应,不会在所有提供商上退还已取消的流式请求费用,也无法让网关本身免受自身故障的影响。以下是它确切停止的地方,以及针对每种情况的应对措施。
| 限制 | 含义 | 你的缓解措施 |
|---|---|---|
| 受限于你的列表 | 当你的 models 数组中的每个模型都出错时,返回最后一个错误 | 将可靠的兜底模型放在 models 的最后 |
| 非错误拒绝 | “坏”但非错误的响应不会触发回退 | 当正确性至关重要时,自行验证响应 |
| 流式取消 | 中止流式请求在某些提供商上仍会计费(包括 Bedrock、Groq、Google、Mistral 等) | 路由到支持可取消流的提供商,或为此预留预算 |
| 网关依赖 | 路由层自身也会出现故障(2025 年 8 月,约 50 分钟) | 在你这边设计重试;关注 status.openrouter.ai |
受你的列表限制,且仅针对已分类的错误
回退会按顺序尝试 models 数组中的每个模型。当最后一个也失败时,该错误会返回给你(model-fallbacks 文档);除了你列出的内容之外,没有其他重试链。
更糟的是,如果某个模型返回 200 状态码但内容是垃圾,回退根本不会触发。OpenRouter 仅在已分类的错误上触发。把你的 models 数组中最可靠的兜底模型放在最后,并在正确性重要时自行验证响应。
流取消在某些提供商处仍会继续计费
当流在客户端停止渲染,但完整的信用费用仍然计入你的账户时,你的第一反应通常是去翻日志。你以为提示词触发了内容审核标记,或者浪费时间去找一个从未发生过的 5xx。
包括 Bedrock、Groq、Google 和 Mistral 在内的一部分提供商不支持流取消(流式传输参考)。当你在响应中途中止流时,你这边连接关闭,但模型在它们那边继续生成(并计费)。
要处理这个问题,请明确将你对成本敏感的流式路径仅路由到支持可取消流的提供商,或为超支预留预算。
网关也是一种依赖
2025 年 8 月,一次约 50 分钟的数据库故障导致路由层宕机。路由层有其自身的单点故障。
Hacker News 讨论帖自己的结论是公允的:“正常运行时间仍然优于任何单一提供商”,但这并非零风险。在你这边设计重试,并关注 status.openrouter.ai 以了解网关级事件。
为生产环境配置故障转移:一份清单
结合两层并加上支出护栏。下面的配置是大多数生产环境想要的形态:一个带有可靠兜底的模型链、默认提供商故障转移保持开启、排除一个已知有问题的端点,以及为用户面向路径设置延迟截止值。
| 步骤 | 操作 |
|---|---|
| 1 | 设置一个 models 数组,将可靠的兜底模型放在最后,这样最终回退就是你最信任的那个。 |
| 2 | 保留 allow_fallbacks: true(默认值),除非合规或 BYOK 合同强制要求单一提供商。 |
| 3 | 使用 ignore 排除你发现服务不佳的提供商端点;每个模型页面上的提供商正常运行时间标签页就是发现它们的方式。 |
| 4 | 为用户面向路径添加 preferred_max_latency 百分位截止值以限制尾部延迟。 |
| 5 | 依赖零完成保险,但设置支出限额并关注活动日志中的 429 边缘情况。 |
| 6 | 监控 status.openrouter.ai 以了解网关级事件。 |
这是每个项目推荐的起始配置。复制它并调整:
from openrouter import OpenRouter
client = OpenRouter(api_key="<OPENROUTER_API_KEY>")
completion = client.chat.send(
model="anthropic/claude-sonnet-4.6",
models=["openai/gpt-5.4-mini", "google/gemini-3.5-flash"], # floor model last
provider={
"ignore": ["deepinfra"], # exclude a known-bad endpoint
"preferred_max_latency": {"p90": 3}, # bound worst-case latency
# allow_fallbacks stays true by default
},
messages=[{"role": "user", "content": "Summarize this thread."}],
)
print(completion.model) # confirm which model answered获取一个 API 密钥,故障转移默认值就已经开启。我们建议在第一天就添加一个 models 数组。这是你将设置的最便宜的安全网。
常见问题
当提供商宕机时,OpenRouter 如何处理故障转移?
对于由多个提供商服务的单个模型,当所选提供商返回 5xx 或限流时,OpenRouter 会自动尝试下一个提供商。这种提供商层故障转移默认开启(allow_fallbacks: true),无需配置(provider-selection 文档)。
提供商故障转移和模型回退有什么区别?
提供商层故障转移通过切换提供商来保持一个模型存活,而且是自动的。模型层回退则通过一个 models 数组完全切换到另一个模型,且需要主动启用。前者可从提供商故障和速率限制中恢复;后者还能从上下文长度错误和审核拒绝中恢复。
OpenRouter 上什么会触发自动回退?
4 种情况:宕机、速率限制、上下文长度验证错误,以及针对被过滤模型的审核标记(model-fallbacks 文档)。宕机和速率限制先在提供商层处理,然后在模型层处理;上下文长度和审核在模型层处理。
OpenRouter 会对失败的请求收费吗?
不会。你只为成功的运行付费;在故障转移耗尽后失败的请求不计费(zero-completion insurance)。请为一个有记录的例外做好规划:用户报告称某些 429 路径和部分输出仍会消耗额度,因此请设置支出限额并检查你的活动日志。
OpenRouter 在生产环境中的可靠性如何?
它使用 30 秒健康窗口和公布的每模型正常运行时间实时绕开提供商故障(uptime-optimization 文档),这使得最坏情况下的正常运行时间优于任何直接集成的单一提供商。它并非零风险:2025 年 8 月的网关故障表明路由层有其自身的依赖项。请设计重试机制并监控 status.openrouter.ai。
如何在 OpenRouter 上设置回退模型?
按优先级顺序传入一个 models 数组。OpenRouter SDK 将 models 作为一等字段,例如 models=["openai/gpt-5.4-mini"];使用 OpenAI SDK 时通过 extra_body 传入(model-fallbacks 文档)。
把你最可靠的模型放在最后,这样最终回退就是你的底线。
来源:OpenRouter:Announcements(RSS) · openrouter.ai