使用负载均衡策略进行路由
本教程演示 GPUStack 的路由级负载均衡策略:在分散负载的同时保持会话粘性,以及通过决策服务为每个请求选择小模型或大模型。配置参考见模型路由管理。
前提条件
- GPUStack 已安装并运行。应用这些策略的 AI 网关默认随 GPUStack 部署,标准安装无需额外配置。
- 已部署两个模型作为路由目标,例如下文使用的
qwen3-0.6b和qwen3-32b。 - 对于决策服务部分:已在
Model-Provider页面将 Jev 决策服务注册为TypeSafe Decision Service (Jev)提供商,参见模型提供商管理。
步骤 1:创建路由
- 打开
Routes页面。 - 点击
Add Route,输入名称,例如qwen3。 - 选择
qwen3-0.6b和qwen3-32b作为Route Targets,不设置任何权重。 - 点击
Save。
没有权重和策略时,路由的 Route By 为 round-robin,即在两个模型之间轮询。
步骤 2:理解会话亲和性与最少在途请求策略的交互
启用策略插件后,每个插件为所有候选目标打分,最终选择器根据加权总分选择目标:
会话亲和性为会话当前归属目标打最高分;最少在途请求策略为最空闲的目标打最高分。因此,只有后者的分差超过前者的分差时,会话才会离开当前归属目标。
两个插件都使用默认权重 1 时,下表展示当前归属目标积累了 x 个在途请求、其他目标全部空闲时的行为;这是最容易发生切换的情况:
| 目标数(N) | x=0 | x=1 | x=2 | x=3 | x=4 | 是否会切换? |
|---|---|---|---|---|---|---|
| 2 | 保持 | 平局 ⚠️ | 切换 | 切换 | 切换 | 是 |
| 3 | 保持 | 保持 | 平局 ⚠️ | 切换 | 切换 | 是 |
| 4 | 保持 | 保持 | 保持 | 保持 | 保持 | 仅在 x ≈ 5.3 时 |
| ≥5 | 保持 | 保持 | 保持 | 保持 | 保持 | 否 |
- 切换:会话迁移到下一个候选目标。
- 平局 ⚠️:两个分差完全相同,最终选择器随机打破平局;同一请求可能迁移,也可能不迁移。
- N ≥ 5:最少在途请求策略的分差上限为
1/(N−1) ≤ 0.25,低于亲和性的分差,因此仅靠负载不均衡无法打破粘性。
要让较大路由中的负载发挥作用,需要重新平衡权重。权重如何工作给出了调整权重比例后的切换阈值。
步骤 3:启用会话亲和性和最少在途请求策略
- 编辑步骤 1 中的路由。
- 启用
Session Affinity,接受默认会话键链,或自行指定。默认依次使用session-id请求头、x-client-request-id请求头,再使用请求体中的prompt_cache_key。 - 启用
Least Inflight Request,使用默认权重。 - 保存,确认路由的
Route By为Policy。
此时会话具备粘性:携带相同会话键的请求会保留在同一目标上,使提示词缓存持续命中;当前目标负载较高时,按上表规则将会话迁移给空闲目标。
不同 API 路径支持的键来源不同:请求头键,例如 session-id,适用于所有路径;prompt_cache_key 等请求体键仅对 /responses 和 /messages 请求生效。/chat/completions 没有标准的请求体会话字段,因此只使用键链中的请求头键。对话流量应优先使用请求头键。
步骤 4:添加决策服务路由
接下来让路由感知模型能力:不再始终将会话固定到最初选择的模型,而是让决策引擎判断每个请求适合哪个模型。
-
编辑路由,启用
Decision Service Routing:Decision Service:选择已注册的提供商。Decision Model:例如jev-latest。Instructions:“选择能够妥善处理请求的最小模型。简单、简短或事实类请求交给快速模型;复杂推理、数学或代码请求交给大模型。”Model Criteria:为每个目标添加一项,也可以点击Generate from targets后再调整:qwen3-0.6b:“非常快速、低成本的 0.6B 模型。适合问候、简单事实问答、格式整理和简短闲聊,不擅长多步推理、数学和代码。”qwen3-32b:“能力较强的 32B 推理模型。适合复杂推理、数学、代码生成和长上下文分析,每次请求较慢且成本更高。”
-
保存后,以路由名
qwen3发送两个经过认证的请求。将$GPUSTACK_API_KEY替换为API Keys页面创建的密钥:
第一个请求会转发到 qwen3-0.6b,第二个会转发到 qwen3-32b。
权重如何工作
权重出现在两个位置,含义不同。
目标权重(流量份额)
在 Target Weight 模式中,目标权重代表该目标的总流量份额,与实例数量无关。GPUStack 会调整实例级权重,确保分流结果始终符合目标权重:
- 目标 A 的权重为 100、运行 1 个实例,目标 B 的权重为 100、运行 2 个实例,两个目标各获得 50% 的流量,并非每个实例各获得 1/3。
- 将一个目标从 1 个实例扩容到 2 个实例,不会改变目标的总份额;各实例会各获得该份额的一半。
例如,qwen3-0.6b 权重为 100,qwen3-32b 权重为 300,则 25% 的请求发往小模型,75% 发往大模型,无论其副本数是多少。
策略权重(在总分中的影响力)
各策略插件的 Weight 控制其在 Policy 模式加权总分中的影响力。权重为正数,小数也有意义。不设置 Weight 时,使用插件内置默认值:Session Affinity 和 Least Inflight Request 默认为 1,Decision Service Routing 默认为 10。
当当前归属目标有 x 个在途请求、其他目标空闲时,会话亲和性与最少在途请求策略的平衡计算如下:
- 会话亲和性分差:
affDiff = 0.5 / (2·(1 − 2⁻ᴺ)) - 最少在途请求分差:
loadDiff = x / ((1+x)·(N−1) + 1) - 当
w_leastInflight × loadDiff > w_affinity × affDiff时,会话切换。
调整权重会改变切换阈值。下表按权重比例(Least Inflight Request : Session Affinity)和目标数 N,列出引起切换的最小在途请求数 x:
| N | 1:1(默认) | 1.5:1 | 2:1 |
|---|---|---|---|
| 2 | 2 | 1 | 1 |
| 3 | 3 | 1 | 1 |
| 4 | 6 | 2 | 1 |
| 5 | 从不 | 3 | 2 |
| 6 | 从不 | 7 | 3 |
| 7 | 从不 | 从不 | 4 |
| 8 | 从不 | 从不 | 9 |
表格解读:
- 默认 1:1 比例下,包含 5 个或更多目标的路由永远不会切换,因为最少在途请求策略的分差上限低于亲和性分差。
- 将 Session Affinity 的
Weight减半,即采用 2:1 比例,会让最多 8 个目标的路由在x= 2–4 时受负载影响;将 Least Inflight Request 的Weight加倍效果相同,因为仅比例影响结果。 - 完全相同的分差,例如 1:1 且 N=2/x=1,由最终选择器随机打破平局。
各策略如何分工
所有已启用策略都参与同一加权总分计算,各司其职:
- Decision Service Routing 判断哪个模型适合请求,默认
Weight为 10,通常具有主导作用。 - Session Affinity 将会话保留在当前模型上,维持提示词缓存的局部性。
- Least Inflight Request 在胜出模型的各实例之间分散请求。
模型部署了多个实例时,决策服务先将选择范围缩小到该模型,再由 Least Inflight Request 在模型内部选择实例。