做多 provider 网关,我们踩过的 5 个坑
ByteSpike 第一版不是这个形状。下面 5 个决定是上生产之后被我们回滚的 —— 写下来便宜、亲历贵。
ByteSpike 某种形态从 2025 Q4 跑到现在。现在这形状 —— Anthropic 兼容为默认、双协议 shim、失败不计费、per-endpoint 费率透明 —— 事后看像理所当然。当时一个都不理所当然。下面 5 个弯路是我们走过然后掉头的,写下来给下一个建造者省一遭。
1. 试图发明厂商中立的抽象层
早 ByteSpike 有自定义中间请求形态 —— 叫 `bs_request` —— 设计上长得像所有 provider 又不像任何一家。我们重做 tool_use、重做 cache_control、重做 thinking block。3 个月后每个新模型上线都要做双向映射,我们的 "中立" 类型其实就是某一家的类型改了名字。掉头:选交付最快那家的 API、原样镜像 wire format、shim 其他人进去。我们选了 Anthropic Messages。
2. 提交就扣钱、失败再返还
credit 账本第一版在提交时扣,5xx / NSFW / 连接断时异步返还。技术上能跑,但每个客户月结都多一栏 refund 需要解释。掉头到两阶段提交 —— 提交时预扣,成功投递时才出账 —— refund 那栏现在永远是空的。失败那行项目根本不存在。(详见 "failures don't bill 实现" 那篇)
3. 想用一个应用做所有事
营销 landing 页 / 客户后台 / API docs 都在同一个 Next 进程里。两周还可爱,两个月就受罪。每次营销文案 fix 得连带 auth 代码路径一起 redeploy。每次后台迭代都要营销侧 smoke test。掉头到 3 个应用(marketing / console / docs)+ workspace package 共享设计 token 和 locale。3 份 deploy 日志 / 3 个影响半径 / 一时刻只能炸一个。(详见 "three-app 架构" 那篇)
4. 让定价跟网关分别存数据库
第一版定价 source-of-truth 是运维维护的 Notion 表,导成静态 config 给网关启动时读。运维改个数字,网关下次重启才发现。某些时段 marketing 站和网关收的钱差两个小时。掉头到网关 admin /channels 端点做单一信源,marketing /pricing 表 JOIN 这个端点的 export。两边同一信源,marketing 页要么跟网关一致,要么离一致只差一次 build。
5. 没 deploy 管线就上线
marketing 站在 lisahost 同一个容器跑了 6 天,我们 ship 20 个 PR 修 cache / SEO / 性能,全没到生产 —— 直到我们手动 `docker build → scp → ssh load → restart` 一次。本周中走到这一步才发现没 CI/CD —— 坦白讲之前没需要过。Lighthouse 报告开始读起来平稳那天我们注意到。掉头进行中:写 GitHub Action 在 merge main 时触发我们已经背熟了的手动步骤。
“每个事后证明错的决定,写它不到一周,掉头要几个月。早期把形状选对的杠杆极大。”
如果你在做相邻的东西 —— 网关 / 多厂商路由 / 聚合产品 —— 上面 5 条不是通则。前 4 条是我们走完别的形状才汇到现在这个形状。第 5 条是我们希望在 cache-debug 兔子洞之前就发现的。你的可能不一样。但几乎肯定有一个、还在等着被掉头。