API中转站错误码怎么统一封装:上游差异映射、重试边界与请求ID透传的落地顺序
同一段业务代码接多家模型,401、429、402 的含义却各不相同,客户端只能靠猜。本文从上游差异、内部错误码分类、映射表设计、重试边界、流式错误事件与计费口径六个角度,拆解 API 中转站错误码统一封装的落地顺序,说明如何让调用方只面对一套稳定契约。
做过大模型接入的团队大多踩过同一个坑:同一段业务代码,在 A 家模型上返回 401 就提示密钥无效,换到 B 家却变成 429,再看 C 家干脆把限流信息塞进 message 字段里。客户端不得不在业务层堆一大串 if-else 去猜,最后错误提示混乱,重试逻辑也写不干净。错误码统一封装看起来是细节,实际决定了一套 API 中转能不能被工程团队长期用下去。
上游差异远不止状态码本身。OpenAI 兼容协议只规定了大体结构,各家在 error.type、error.code 与 HTTP 状态码的对应关系上各有各的习惯。有的把上下文超长归到 400,有的归到 422;有的在额度不足时返回 402,有的仍返回 429。流式场景更麻烦,响应头已经发出 200,中途出错只能通过 SSE 的 error 事件告知,如果封装层没处理,客户端会拿到一段半截文本却以为成功了。
统一封装的核心目标,是让调用方只面对一套稳定契约。这里面至少要固定四件事:内部错误码、对应的 HTTP 状态码、是否可重试的布尔标记,以及贯穿全链路的 request_id。调用方只要判断 code 属于哪一类,就能决定是提示用户、切换模型还是直接退避重试,而不是去读 message 里的自然语言。message 可以保留人类可读信息,但不能作为程序判断依据。
分层是落地前提。通常分为接入层、适配层与封装层:接入层负责鉴权、限流与 Key 额度校验,适配层负责把各上游的原始响应翻译成内部结构,封装层再统一输出。三层分开之后,新增一个上游只需要在适配层补一张映射表,不会牵动业务调用方。反过来,如果把映射逻辑写进业务代码,模型一多就会失控,改一处错一处。
错误码分类建议按调用方的处置动作来划分,而不是按上游来源划分。常见类别包括参数与格式类、鉴权与权限类、额度与计费类、限流与并发类、上游服务异常类、内容安全类。分类的价值在于同一类错误的处置方式一致:限流类统一走指数退避加抖动,上游异常类允许切换备用通道,内容安全类则不应重试,重试只会重复消耗额度。
映射表的键值设计要考虑可扩展。以内部错误码为主键,值为一组映射规则,规则里包含上游标识、原始 HTTP 状态码、原始 error.code 或 error.type 的匹配条件。同一个内部错误码可以对应多条规则,不同上游各占一条。映射表最好以配置形式维护,改一行配置就能上线,走代码发布会拉长故障修复时间,对中转这种高频变更的场景尤其不划算。
重试策略必须和错误码绑定。可重试的典型是连接超时、上游 5xx 与限流;不可重试的是参数错误、鉴权失败与内容被拦截。重试要带指数退避和随机抖动,避免同一时刻大量请求同时打回上游。同时要给重试设上限并记录每次尝试的 request_id,否则一个慢上游会把整条链路拖住。非流式对话一般可重试,带副作用的工具调用则要谨慎。
流式响应里的错误封装是很多中转站忽视的一环。HTTP 状态码在首个数据块发出时就已经确定,后续上游异常只能以事件形式下发。稳妥做法是:在 SSE 流中定义统一的 error 事件结构,字段与普通错误响应保持一致,同时明确告知调用方本次输出不完整。客户端据此决定是丢弃已收内容还是回退重试。若封装层只发一个连接中断,调用方很难区分是网络抖动还是上游故障。
错误码和计费是相互牵连的。调用失败是否计费,得看失败发生的位置:请求还没打出去就失败,不应该产生消耗;上游已经生成了一部分 token 再中断,就要按实际用量结算。因此错误响应里带上用量信息很重要,流式场景尤其如此。快米兔 API 采取按量计费的方式,注册即送 5 元测试金,开发者可以先用小额度把各类错误分支都跑一遍,再决定生产接入方案。
可观测性别只盯着日志。每一层都透传同一个 request_id,日志、告警、对账才能串成一条链路。错误码维度的监控要能看出趋势:某个上游的限流类错误是不是突然上升,某类参数错误是不是集中在少数调用方。把这些指标做成看板,问题定位就从翻日志变成看曲线。此外,错误信息里不要回显完整 Key 或用户敏感数据,转译阶段就要做脱敏。
文档和错误码清单要同步维护。调用方真正需要的是四项信息:错误码含义、HTTP 状态码、是否可重试、建议处置动作。只给一张码表而没有处置建议,接入方还是要靠猜。快米兔 API 在兼容 OpenAI 协议的基础上,把错误结构统一成一种格式,调用方更换模型时不必重写异常分支,这类细节比多接几个模型更能减少长期维护成本。
最后给一份落地顺序:先定内部错误码全集与分类;再梳理上游差异,建映射表;然后统一响应结构与 request_id 透传;接着补重试、退避与流式错误事件;最后接监控告警与文档。顺序颠倒容易返工,尤其是先写重试再定错误码,很可能把不可重试的错误也重试掉。错误码统一封装没有太多炫技空间,但它决定了一套中转服务是能用,还是敢用在生产。
