登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  科技周边 >  人工智能

LiteLLM Router 怎样让同一模型组故障时切换其他部署

来源:17golang原创

时间:2026-11-05 13:14:21 322浏览 收藏

如果同一个模型在两个区域各有一份部署,故障时最稳妥的切换通常是“先换同模型的健康副本”,而不是马上降级到另一个模型。LiteLLM Router 可以把多个配置项放进同一个 model_name 模型组,再用 enable_weighted_failover=True 让异步请求在可重试故障后按剩余部署的权重重新选择。

官方地址:https://docs.litellm.ai/docs/routing

关键配置是 routing_strategy="simple-shuffle" 加上 enable_weighted_failover=True。前者负责按权重选部署,后者负责在同一模型组内排除刚失败的部署并重选;同组部署都耗尽后,才轮到跨模型组的 fallback。

先把基线定义成“同一个模型的多份部署”

本例假设 gpt-6-luna 在两个区域各有一个部署。两个条目的 model_name 必须完全相同,litellm_params.model 和 api_base 则可以不同。这样 Router 看到的是一个模型组,而不是两个需要业务代码手工判断的模型。

为了让后面的切换路径容易复盘,给主区域权重 3,备用区域权重 1。这个比例只影响初次选中的概率,不代表故障时永远先选主区域,也不等于跨组 fallback 的优先级。

LiteLLM 同一 model_name 下的两个部署、权重和 simple-shuffle 路由边界静态结构图
图1:静态结构图,展示 model_name、两个区域部署、weight、simple-shuffle 和 weighted failover 的关系,不是运行截图。

配置同组部署和 weighted failover

下面的 SDK 配置只保留与同组切换有关的字段。示例使用环境变量承载凭据,避免把密钥写进代码;两个部署的模型能力应由你的供应商配置保证一致。

import os
from litellm import Router

model_list = [
    {
        "model_name": "gpt-6-luna",  # 两个条目相同,才能进入同一个模型组
        "litellm_params": {
            "model": "azure/gpt-6-luna",
            "api_base": "https://eastus2.example.azure.com",
            "api_key": os.environ["AZURE_EASTUS2_KEY"],  # 凭据从环境变量读取
            "weight": 3,  # 正常选路时更偏向这个部署
        },
    },
    {
        "model_name": "gpt-6-luna",  # 与上面相同,表示同一模型组的备用部署
        "litellm_params": {
            "model": "azure/gpt-6-luna",
            "api_base": "https://swedencentral.example.azure.com",
            "api_key": os.environ["AZURE_SWEDEN_KEY"],
            "weight": 1,
        },
    },
]

router = Router(
    model_list=model_list,
    routing_strategy="simple-shuffle",  # weighted failover 依赖这个策略
    enable_weighted_failover=True,  # 失败后优先在同组剩余部署中重选
    max_fallbacks=2,  # 限制一次请求最多增加的故障切换跳数
)

这里的 weight 是部署级参数,enable_weighted_failover 是 Router 级开关。不要把备用区域写成另一个 model_name,否则它就不再是本题讨论的同组候选。

用异步入口让请求在同组内重选

weighted failover 的关键不在配置文件里出现一个“备用地址”,而在失败后重新进入同组选择逻辑。LiteLLM 会记录失败部署的 ID,把它放进 metadata._failover_excluded_ids,后续选择只面对没有被排除的同组部署。

import asyncio

async def call_model(router):
    # 使用 async 入口,才能启用 weighted failover 的同组重选路径
    response = await router.acompletion(
        model="gpt-6-luna",  # 请求模型组别名,而不是写死某个区域
        messages=[{"role": "user", "content": "请概括这段文本。"}],
    )
    return response


asyncio.run(call_model(router))

一次请求的判断可以概括为:先按 weight 选一个部署;如果出现可重试的供应商错误,就把失败部署加入排除集合;再对剩余部署重新按权重选择。排除集合会沿着这次请求链累积,因此不会在同一次请求里立刻选回刚失败的副本。

LiteLLM weighted failover 的失败部署排除、同组重选、冷却和跨组 fallback 边界静态结构图
图2:边界结构图,展示失败部署 ID、排除集合、剩余部署、max_fallbacks、cooldown 与跨组 fallbacks 的关系,不是运行结果截图。

用 max_fallbacks 和 cooldown 控制故障成本

max_fallbacks 控制一次请求最多继续尝试多少次,默认值是 5。部署数量少时可以显式设为 1 或 2,避免故障请求在长链路中放大延迟;部署数量多时则要保证它至少覆盖你希望尝试的同组副本数。

router = Router(
    model_list=model_list,
    routing_strategy="simple-shuffle",  # 保持与 weighted failover 兼容
    enable_weighted_failover=True,
    max_fallbacks=2,  # 两份副本时足够覆盖一次主备切换
    allowed_fails=1,  # 连续失败超过阈值后冷却单个部署
    cooldown_time=30,  # 冷却 30 秒,健康副本仍可继续接收请求
)

冷却作用在单个部署,不会把整个 model_name 模型组一起标记为不可用。它解决的是“坏副本反复被选中”的问题,而 weighted failover 解决的是“当前请求如何换到同组其他副本”的问题,两者可以同时存在。

不要把同组切换误写成跨模型降级

如果系统还配置了 fallbacks,它通常代表另一个模型组。weighted failover 会先尝试当前 model_name 的剩余部署,直到同组候选耗尽或达到 max_fallbacks,才进入跨组 fallback。因此,主模型与降级模型应在配置和监控上明确区分。

场景先发生的动作结果边界
初次请求在同一 model_name 内按 weight 选部署权重只表达正常选路偏好
同组部署可重试失败排除失败部署并按剩余权重重选异步入口才走 weighted failover
同组候选耗尽交给既有 fallback 或返回错误可能切换到另一个模型组
上下文窗口或内容策略错误走专门的错误处理路径不应把它当作普通区域故障重试

发布前按三组指标做配置复盘

不要只看“请求最后返回了 200”。可以用三组可复现的配置指标检查路由是否符合预期:同组部署数(本例为 2)、单次请求允许的跳数(本例为 2)、以及跨组 fallback 是否只在同组尝试之后发生。压测时分别让主部署返回可重试错误、让两个部署都失败,再观察请求日志中的部署 ID 和错误类型。

如果失败后又回到同一个部署,先检查是否误用了同步 router.completion()、是否把两个条目写成了不同的 model_name,以及 routing_strategy 是否仍是 simple-shuffle。如果直接切到其他模型,检查跨组 fallbacks 配置和 max_fallbacks 是否过小。

常见问题

两个区域的 model_name 必须一样吗? 对本题的同组 weighted failover 来说必须一样;不同名称会形成不同模型组。

weight 越大是不是故障优先级越高? 不是。它描述正常选择概率;故障时先排除失败部署,再在剩余候选中重新按权重选。

同步调用能不能使用同组故障切换? 文档明确的 weighted failover 路径由异步入口启用;同步入口会落回普通 fallback 逻辑,不能按同样的语义假设。

什么时候应该配置跨模型 fallback? 只有你接受模型能力、价格或上下文行为可能变化时再配置,并在监控里把它和同组区域切换分开统计。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>