Portkey 网关避坑指南:429 重试、多模型 Fallback 与负载均衡的完整配置
【免费下载链接】gatewayA blazing fast AI Gateway with integrated guardrails. Route to 1,600+ LLMs, 50+ AI Guardrails with 1 fast & friendly API.项目地址: https://gitcode.com/GitHub_Trending/ga/gateway
线上复盘:某次大促期间,业务对 OpenAI 的调用连续返回 429,随后夹杂 503,应用层的 while 循环重试又触发限流雪崩。Portkey 是一个配置驱动的 AI 网关,把自动重试、负载均衡、多模型降级声明在一份 JSON 配置里,挂在请求头上传入网关即可。读完本文,你可以直接产出一份带超时、限流和 traceID 追踪的生产级网关配置。
📌 一张图 + 几行代码讲清楚
Portkey 网关位于应用与所有 LLM Provider 之间,兼容 OpenAI 的调用签名:业务代码只改 baseURL 和请求头,重试、降级、缓存全部由网关按配置执行。
下面这段是最小可运行接入,配置在客户端初始化时注入,之后所有请求自动继承:
import { Portkey } from 'portkey-ai'; const portkey = new Portkey({ apiKey: process.env.PORTKEY_API_KEY, config: JSON.stringify({ retry: { attempts: 3, on_status_codes: [429, 500, 502, 503, 504] } }) }); const res = await portkey.chat.completions.create({ model: 'gpt-4o', messages: [{ role: 'user', content: '列出世界七大奇迹' }] });要点:
config支持配置 ID 或内联 JSON 对象,SDK 会将其写入x-portkey-config请求头,网关按此编排每次请求。retry.attempts上限 5 次;on_status_codes缺省时默认重试[429, 500, 502, 503, 504]。- 不想要某个状态码参与重试,显式传
on_status_codes覆盖即可。
🔁 按问题组织的核心场景
429 自动重试的最小配置
现象:业务日志出现大量 429(rate limit exceeded),偶发 500/503;应用层手写循环重试时,同一时刻打满更多配额,限流窗口反而拉长。
根因:OpenAI 等 Provider 的 429 是临时性错误,通常几百毫秒到数秒后恢复;手写 for 循环无法对齐 Provider 声明的退避时间,且把重试逻辑耦合进了业务代码。
最小配置:
{ "retry": { "attempts": 3, "on_status_codes": [429, 500, 502, 503, 504], "useRetryAfterHeader": true } }生效条件与预期效果:
- 429 响应若带
retry-after/retry-after-ms头,网关按该值等待后重试,而非固定间隔盲等。 - 全部重试失败后,网关把最后一次响应原样透传,不会吞掉原始错误。
- 注意全局硬上限:所有重试总耗时不得超过 60s,超过即放弃并透传最后一次结果,所以"重试 5 次 + 每次 30s 超时"这类配置不会被真正执行完。
- 实现位于 src/handlers/retryHandler.ts,退避与 408 超时逻辑都在这里。
多模型降级怎么写
现象:重试耗尽后业务仍拿到 500/503;或单个 Provider 区域性故障,所有重试都打在同一账号上,全部失败。
根因:单账号单模型的可用性受 Provider 侧故障与限流双重约束,重试只能解决"临时抖动",解决不了"持续不可用"。
最小配置——在根目标上声明fallback链,每个目标可独立设置重试与缓存:
{ "targets": [ { "provider": "openai", "retry": { "attempts": 2, "on_status_codes": [429, 500] }, "fallback": { "targets": [ { "provider": "anthropic", "model": "claude-3-5-sonnet-latest" }, { "provider": "groq", "model": "llama-3.3-70b-versatile" } ] } } ] }生效条件与预期效果:
- 主目标重试 2 次仍命中 429/500 后,按序切到 Anthropic、Groq,业务层拿到的仍是标准 OpenAI 格式响应。
- 切换对业务代码透明,无需改请求参数;但注意各 Provider 对
max_tokens等字段的必填要求不同(如 Anthropic 强制要求max_tokens),配置里建议用override_params显式指定。 - 排查降级是否触发时,给请求传
traceID,日志页可直接按 ID 过滤出完整调用链。
负载均衡 + 嵌套 Fallback 的生产级配置
现象:单账号 RPM 配额在高峰期被打穿,429 占比超过 10%;单纯加账号但代码里写死请求地址,扩容要发版。
根因:单 Provider 的限流是硬约束,水平扩容的唯一手段是把流量拆到多账号/多 Provider,再给拆分结果兜底。
最小配置——loadbalance按权重分流,嵌套fallback兜底:
{ "strategy": { "mode": "loadbalance" }, "targets": [ { "virtual_key": "anthropic-vk", "weight": 0.5, "override_params": { "model": "claude-3-5-sonnet-latest", "max_tokens": 200 } }, { "strategy": { "mode": "fallback" }, "weight": 0.5, "targets": [ { "virtual_key": "openai-vk" }, { "virtual_key": "azure-openai-vk" } ] } ] }生效条件与预期效果:
- 50% 流量走 Anthropic,50% 进入 OpenAI → Azure OpenAI 的降级链,任一目标不可用时流量自动落到下一层。
weight支持 0:把某个账号权重置 0 即可在线摘除,恢复时调回来,不需要改代码。- 同 Provider 可挂多个账号的 virtual key,等效于把可用 RPM 配额乘以账号数。
- 路由与降级过程可通过 traceID 在日志中逐跳还原,完整流程参考 cookbook/getting-started/resilient-loadbalancing-with-failure-mitigating-fallbacks.md。
✅ 生产落地检查清单
| 检查项 | 说明 |
|---|---|
| 鉴权 | 业务侧只持有 PortkeyapiKey,Provider 密钥以 virtual key 形式入网关密钥库,conf.example.json展示了credentials与integrations的写法,代码仓库不落明文 key |
| 超时 | 在配置里显式设置timeout(毫秒),超时请求由网关直接拒绝并返回 408,避免业务线程被挂起 |
| 限流 | 在integrations的rate_limits中按rph配置账号级 RPM/Token 上限,先于 Provider 侧限流触发 |
| 降级 | 每个生产链路至少 2 个目标:loadbalance 权重可置 0 在线摘除,fallback 链兜底持续故障 |
| 可观测性 | 给请求传traceID,日志页可过滤出降级/重试的完整调用链、token 数与成本 |
| 预算 | attempts上限 5、总重试窗口 60s 是硬约束,配置更激进的值也不会真正执行 |
网关配置编排的核心逻辑在 src/handlers/handlerUtils.ts,配置从请求头解析、继承到逐目标下发的完整链路都在这里。
延伸资源:
- 网关配置入门:cookbook/getting-started/writing-your-first-gateway-config.md
- 自动重试细节:cookbook/getting-started/automatic-retries-on-failures.md
- 自部署与 K8s 部署说明:docs/installation-deployments.md
【免费下载链接】gatewayA blazing fast AI Gateway with integrated guardrails. Route to 1,600+ LLMs, 50+ AI Guardrails with 1 fast & friendly API.项目地址: https://gitcode.com/GitHub_Trending/ga/gateway
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考