在 AI SaaS 平台中,你不可能只接一家模型供应商。需要接多家供应商来保障稳定性、控制成本和备份容灾。但多供应商带来的问题是:当某条线路异常时,如何在不影响用户体验的前提下自动切换?如何避免已经被官方频控的线路继续接收请求?
下面是我在实际项目中落地的一套供应商路由与线路保护方案。
一、供应商路由核心逻辑
ProviderRouterService 是整个路由的决策中心。每次 AI 任务提交时,路由服务需要回答:用哪家供应商的哪个模型?
获取可用供应商
1 | public List<ProductProviderDO> getAvailableProviders(Long productId) { |
智能路由排序
当存在多条候选线路时,按成功率和降权策略排序:
1 | public List<ProductProviderDO> getSmartRoutedProviders(Long productId) { |
滑动窗口成功率
使用 ConcurrentLinkedDeque 维护每个供应商最近 20 次调用的结果,只计算 10 分钟内的:
1 | private static final int WINDOW_SIZE = 20; |
阶梯式熔断
失败越多,熔断越久。3 次失败起开始保护:
1 | private static final int FAIL_THRESHOLD = 3; |
二、错误分类服务
不是所有失败都该惩罚供应商。AiProviderErrorService 对上游异常做一次性分类,调用方根据返回的决策对象处理路由、退款和提示:
1 |
|
频控检测与自适应退避
1 | public boolean isRateLimited(Throwable error) { |
用户可见错误文案
对上游返回的英文错误做”翻译”,生成可读的中文说明,同时不暴露敏感信息:
1 | public String translateUpstreamError(String raw) { |
三、记录成功与失败
调用完成后,分别走成功和失败记录路径:
1 | // 成功:清理故障计数,清除短冷却和频控状态 |
四、后台健康可视化
管理员在后台可以看到每条线路的实时健康快照:
1 | public record ProviderHealthSnapshot( |
五、设计原则
- 每条线路独立保护:不能因为 Vidu 挂了就把所有视频生成一刀切锁死
- 全保护态放行半开探测:不会让模型永远不可用,探测成功自动恢复
- 内容安全不污染供应商:图片/视频不合规是模型能力边界,不是线路故障
- 429 自适应退避:连续 429 后延长冷却,尊重
Retry-After头部 - 用户错误提示不泄漏:说明失败阶段,但不透出 API Key、Token 和完整响应
这套方案跑了一段时间后比较稳定,当前还在观察多实例部署下的短冷却同步问题——后面多实例同时 429 的话,可能需要在 Redis 中维护全局冷却状态。