← 返回资讯

New API 渠道测试失败:四层排查法十分钟定位问题

2026-08-07

在网关后台加了一个上游渠道,点测试,红了。报错通常就一句话,比如”请求失败""连接错误""渠道不可用”,看不出任何有用信息。

这时候大多数人的反应是回去把配置从头看一遍,看不出问题就换个模型再试,还不行就重启容器,再不行去搜别人有没有遇到过一样的报错。这个过程可能花掉一下午,而最后发现原因是 key 复制时多带了一个换行符。

问题不在于这些原因有多难,而在于它们横跨四个完全不同的层次:网关那台机器到上游的网络能不能通、地址和路径拼得对不对、凭证有没有被上游认下、请求里的模型名上游认不认识。这四层里任何一层断掉,网关给你的都是那句差不多的红字。乱查就是在四个层次之间来回跳,查完一遍还不敢确定哪层已经排除了。

按层查就快得多。下面这套顺序我用了很久,正常情况下十分钟内能把问题锁到某一层。本文只讲方法,不涉及具体后台的菜单位置和字段名称——那些各版本会变,一律以你手上后台页面的提示和官方文档为准。方法本身跟界面长什么样没关系。

为什么排查顺序比排查技巧更重要

先说清楚这套顺序的设计逻辑,理解了逻辑你自己也能推出来。

四层之间是有依赖关系的:网络不通,鉴权无从谈起;地址不对,key 再正确也没用;地址和鉴权都对了,模型名写错才会暴露出来。所以从底往上查,每查完一层,上面的层次都还在待定状态,但下面的层次已经被永久排除了。这就是”按层”的全部价值——单调地缩小范围,不回头。

反过来从上往下查就不行。你先怀疑模型名,改了个模型名再测,还是失败,你没法判断是新模型名也错了,还是问题根本不在这一层。信息量为零,时间白花。

四层的顺序是:

问什么典型症状
1. 网络与上游本身网关那台机器能不能直接调通上游超时、连接被拒、DNS 解析失败
2. 地址与路径base_url 与实际请求路径拼出来对不对404、返回一段 HTML 而不是 JSON
3. 鉴权上游认不认这个凭证401、403
4. 模型标识符请求里的模型名上游认不认识模型不存在,有时候长得像权限错误

第一层:先绕过网关,在网关那台机器上直接 curl 上游

这一步是整套方法的核心。做完它,问题被一刀切成两半:要么是上游或凭证的问题,要么是网关配置的问题,中间没有灰色地带。

做法是登录到网关所在的那台机器(容器化部署就进到容器里,或者在宿主机上执行,两者可能有区别,后面会说),用最原始的 curl 直接打上游的接口,带上你准备填进网关的那把 key,请求你准备用的那个模型。不经过网关的任何一行代码。

结果只有两种:

  • curl 通了。 那么上游服务正常、这台机器出得去、这把 key 有效、这个模型名上游认识。这四件事一次性全部确认。剩下的问题百分之百在网关侧的配置上——你怎么填的、网关怎么拼的。
  • curl 不通。 那么问题在网关之外,继续调网关的配置是纯浪费时间。此时按 curl 返回的具体错误往下走第二、三、四层,但排查对象是你的 curl 命令和上游,不是网关。

为什么必须在网关那台机器上执行

这句话是这一步的关键,很多人做了 curl 但做错了地方,在自己笔记本上跑通了就以为上游没问题,然后回头继续折腾网关配置。

你本地和网关服务器是两个完全不同的网络环境,至少有三处可能不一样:

出网策略。 生产服务器通常挂在有出方向限制的网络里——安全组、防火墙规则、云厂商的 NAT 网关配置。很常见的一种情况是这台机器只被放行了少数几个目的地址,你新加的那家上游不在名单里。你本地当然畅通无阻,服务器上就是超时。

DNS。 服务器可能用的是内网 DNS,或者容器里用的是 Docker 自己的 DNS 配置。你本地能解析的域名,容器里未必能解析,报错会是 DNS 相关的失败而不是连接失败——这两者要分清楚,是不同的处置方向。

代理。 你本地可能有一个代理软件在后台开着,你已经忘了它的存在。服务器上没有。或者相反:服务器上配了全局代理环境变量,而代理本身对某些目的地址不通。

所以在自己机器上 curl 通了,只能证明上游服务和 key 是好的,不能证明网关连得上。这个结论也有价值,但它不是这一步要的那个结论。要严谨,就得在网关跑的地方跑。

容器化部署时还有一层:宿主机能出去,不代表容器能出去,容器的网络模式和 DNS 是独立配置的。如果宿主机 curl 通而容器里不通,方向就已经很清楚了,去查容器网络,别再看网关配置。关于容器化部署本身的配置选择,可以参考 New API 部署实操 里关于部署形态的部分。

这一步的产出要记下来

curl 成功时,把那条完整的命令保存到你的运维笔记里,注释上日期。它以后有两个用途:一是上游哪天出问题时,你可以用同一条命令一秒钟确认是不是上游挂了;二是网关升级或迁移之后,它是你的回归测试基线。

第二层:地址与路径,症状通常是 404 而不是 401

curl 通了,问题在网关侧,接着查地址。

这一层最容易出问题的原因是:各家上游的 OpenAI 兼容地址路径规则根本不统一。同样是”OpenAI 兼容接口”,路径能长出好几种形态:

形态例子
域名 + /openai/v1https://api.groq.com/openai/v1
域名 + /v1/openai(两段顺序反过来)https://api.deepinfra.com/v1/openai
域名 + /openai(没有 /v1https://api.novita.ai/openai
域名 + /inference/v1(多一段)https://api.fireworks.ai/inference/v1
域名 + /v1/带末尾斜杠https://api.tokenfactory.nebius.com/v1/

(以上均取自各平台官方文档,路径可能调整,实际以官方文档当次为准。)

看着都差不多,抄错一段就全盘不通。而这一层真正的坑在于:网关侧填的到底是 base 还是完整路径,取决于网关怎么拼。

有的实现是你填 base,它自己在后面接具体的端点路径;有的是你填到哪儿它就用到哪儿。如果网关会自动补 /v1,而你把带 /v1 的完整地址填了进去,拼出来就是重复的 /v1/v1;反过来网关不补而你只填了域名,拼出来就少一段。两种情况都会失败,且报错通常是 404,而不是 401

这个症状区分很有用:

  • 拿到 404,先查地址和路径,别去查 key。404 的语义是”这个地址上没有这个东西”,跟你是谁没关系。
  • 拿到的响应不是 JSON 而是一段 HTML,那基本可以确定路径打到了对方的网站或者某个反代的默认页上,同样是地址问题。

判断网关怎么拼的最可靠办法不是猜,是对照第一层那条 curl 命令。你 curl 时用的是完整 URL,把它和网关里填的值放一起比对,看差了哪一段,缺的那段就是网关本该补而没补的、或者你多填了的。至于填法本身,按后台页面上的提示和官方文档来。

更细的路径差异和它们各自的坑,七家推理平台的模型 ID 那篇里有横向对照。协议兼容层面上”OpenAI 兼容”到底兼容到什么程度,可以看 OpenAI 兼容协议

第三层:鉴权,先分清 401 和 403

地址对了还是不行,查凭证。这一层最先要做的是把两个状态码分开,它们指向完全不同的处置方向。

401 的意思是”我不知道你是谁”。 凭证没被识别——没带、格式不对、被截断、已经失效、或者根本不属于这个平台。处置方向是凭证本身。

403 的意思是”我知道你是谁,但不让你做这件事”。 身份是认下来的,被拒的是这个具体操作——账户没开通这个能力、这把 key 的权限范围里不包含它、组织层面有限制、或者欠费停用。处置方向是账户和权限,不是重新贴一遍 key。

我见过很多人拿到 403 之后一遍遍重新生成 key、重新粘贴,白折腾半天。分清这两个码,能省掉整段错误方向的排查。

最常见的原因是最低级的那个:首尾空白

复制 key 的时候带上了首尾空白——空格、换行、制表符——这是我见过占比最高的单一原因,没有之一。

它为什么这么顽固,因为它看不见。你在配置里盯着那一行看十遍也看不出末尾多了个换行符。而且它有好几个来源:从网页上双击选中时多选了一格;从终端输出里复制时带上了行尾;文本编辑器在保存时自动补了个末尾换行;从聊天软件里粘过来时对方发的就带着空格。

有效的验证办法只有一个:别用眼睛看,用长度看。 把凭证的字符长度打出来,跟你从上游控制台里拿到的原始值对一下。差 1 个字符,就是末尾多了个换行。这招还有个变体是把首尾各几个字符打出来(中间打码),一眼能看出边界上有没有多余的东西。

第一层的 curl 在这里又有用了:curl 命令里的 key 是你手打或粘贴进去的,如果 curl 通了而网关里不通,那两处的 key 值大概率不一样,差别很可能就在空白上。

环境变量名各家不同

如果你的凭证是通过环境变量注入的,还有一个坑:各家上游用的环境变量名不统一,而且不只是前缀不同,后缀也不同——有的用 *_API_KEY 这种形态,有的用 *_TOKEN。你按照肌肉记忆写了个 *_API_KEY,而那家用的是 *_TOKEN,读出来就是空值。

空值造成的 401 特别有迷惑性,因为你会觉得”我明明配了啊”。查法是在启动日志里把生效的凭证做打码输出——不是输出配置文件里写了什么,是输出程序实际读到的那个值。这两者之间隔着环境变量名拼写、进程有没有重启、配置有没有被别的地方覆盖等一大堆可能性。

401 的完整排查清单在 401 报错怎么排查 里写得更细,这里不重复。

第四层:模型标识符,报错可能长得像权限问题

前三层都对了,最后一层是模型名。

这一层单独拎出来,是因为它有一个非常反直觉的特性:模型名写错,报错有时候不长得像”模型不存在”,而长得像权限问题。

原因不难理解。很多上游的模型标识符是两段式或三段式的——前面是发布方或组织,后面才是模型名。你少写了组织前缀,从平台的视角看,你请求的是一个它无法归属到任何公开模型的标识符,返回的信息就可能落到”你没有权限访问”这一类。

后果是排查方向直接跑偏:你会去查 key 的权限、查账户开通了什么、准备去申请白名单,折腾很久,问题其实在那个漏写的前缀上。

所以到了这一层,先把请求里实际发出去的模型名完整打印出来看一眼,再去想权限。这一眼花一秒钟。

网关侧的模型列表与请求里的模型名必须对得上

网关这一层还多了一个独有的坑:渠道上配的”这个渠道支持哪些模型”,和实际请求体里写的模型名,是两个地方,必须严格一致。

一致性至少涉及三件事:

  1. 字符串完全相同。两段式标识符通常是大小写敏感的,DeepSeek-V3 不是 deepseek-v3。有些配置框架会自动把配置值转小写,这个行为要关掉。
  2. 前缀完整。组织前缀属于标识符的一部分,不是可选的装饰。
  3. 映射关系明确。如果网关支持给模型起别名,那么你要清楚请求里写的是别名还是真名,以及别名映射到的目标在这个渠道上存不存在。

典型的失败方式是:渠道的模型列表里配了一批模型名,请求时用的是另一个拼法。网关按请求里的名字去找匹配的渠道,找不到,报”没有可用渠道”——而你明明看着后台里那个渠道好好地开着。这时候不要去查渠道的开关状态,去比对两处的字符串。

多节点部署时的额外坑:两个 secret 必须一致

上面四层针对的是单节点。如果你把网关部署成了多个节点跑在负载均衡后面,还有一类问题需要单独说,因为它的表现根本不像配置错误

New API 的环境变量里,SESSION_SECRET 在多节点部署时必须设置,并且所有节点必须设成同一个值。另外 CRYPTO_SECRET 是缓存键的 HMAC secret,它默认取 SESSION_SECRET 的值——也就是说前者没配好,后者跟着一起不一致。

不一致会怎样?最典型的现象是”时不时被登出”。你在后台点着点着突然回到登录页,重新登进去又好了,过一会儿又被踢。这个现象极难复现,因为它取决于你这次请求被负载均衡分到了哪个节点:分到签发会话的那个节点就正常,分到另一个节点就认不出你的会话。刷新几次可能又好了,你会以为是网络抖动。

而当你在这种状态下调渠道配置,排查就彻底乱了套——你在 A 节点上改的配置,在 B 节点上的缓存行为可能不一样;你测试渠道时的会话是不是有效的,本身就在随机波动。这时候你查到的任何现象都不可信。

所以给一条明确的判断规则:多节点部署下,如果你观察到节点之间行为不一致,或者出现无法解释的登出、缓存行为诡异,先去核对这两个 secret,再回来查渠道。 顺序反了就是在流沙上排查。

这两个变量的具体配置方式以官方仓库 README 当次为准。同理,多节点部署时数据库和缓存也必须是所有节点共享的外部服务,不能各跑各的本地文件。

加渠道的正确顺序:五步,每步只引入一个变量

排查方法讲完了,反过来说一下怎么加渠道才不需要排查。这个顺序的原则只有一条:每一步只引入一个新变量,出问题时候选原因唯一。

第一步:先在网关那台机器上 curl 通上游。 理由前面说透了——这一步把”上游和凭证”这半边彻底确认掉。没通就不要往下走,此时加进网关只会把一个明确的问题变成一个笼统的红字。

第二步:再加进网关,先只填最必要的配置。 别一次性把所有可选项都填满。可选项越多,出问题时候选原因越多。先用最小配置让渠道跑起来,之后再逐项加。

第三步:用一个最小的模型测一次。 挑上游里最便宜、最基础的那个模型,发一条最短的请求。理由有三个:便宜,测试成本可以忽略;快,反馈周期短,你可以多试几次;而且它把”链路通不通”和”某个大模型有没有开通权限”这两件事分开了——很多上游的高端模型需要单独申请,用它做首测,一个链路问题会被伪装成权限问题。

第四步:链路确认通了,再放开模型列表。 这时候每加一个模型,都是在验证”这个具体的模型名在这家上游存不存在、账户开通没有”,而不是在验证链路。这两类问题被彻底分开了,加十个模型出错三个,你能立刻知道是那三个模型名或权限的事,不用怀疑链路。

第五步:最后才接生产流量。 而且不要一次性切过去。先给这个渠道很低的权重或者很小的流量比例,跑一段时间,看有没有偶发的失败——有些问题只在一定量级下才暴露:上游的速率限制、连接池耗尽、长尾超时。这些在单次测试里全都看不见。

不知道上游的限速数值时怎么稳妥起步?把并发压到很低的水平开始,观察一段时间没有异常再逐步往上加;同时把重试和退避准备好,退避要用指数形式并加随机抖动,避免所有失败请求在同一时刻重来一次把上游打得更狠。这个过程本身也会让你摸出自己的实际可用容量,比问到一个数值更靠谱。

自查清单

渠道测不通时,从上往下依次做,做完一条打一个勾:

  1. 在网关那台机器上(容器化就进容器)用 curl 直接调上游,带上同一把 key、同一个模型名。通了就确认问题在网关侧配置,不通就别再动网关。
  2. 拿到的是 404 或者一段 HTML?去查地址与路径,把 curl 里的完整 URL 和网关里填的值逐段比对,看差了哪一段。
  3. 拿到的是 401 还是 403?401 查凭证本身,403 查账户与权限范围,别把 403 当成 key 错了。
  4. 字符长度核对凭证有没有带首尾空白,别用眼睛看配置文件。
  5. 凭证走环境变量注入的,在日志里打出程序实际读到的打码值,确认变量名没写错、进程重启过。
  6. 把请求里实际发出的模型名完整打印一次,检查组织前缀有没有漏、大小写对不对,再去怀疑权限。
  7. 比对渠道上配置的模型列表与请求里的模型名,两处字符串必须完全一致。
  8. 多节点部署的,核对所有节点的 SESSION_SECRET 是不是同一个值(CRYPTO_SECRET 默认跟随它);出现随机登出或节点行为不一致时,先修这个再查渠道。

所有具体的配置位置、字段填法、环境变量的设置方式,以你手上后台页面的提示和官方仓库 README 当次为准——这类项目迭代快,界面和参数都可能已经和某篇文章里写的不一样了。但上面这套排查顺序不依赖界面,它只依赖”每次只引入一个变量”这个原则,换成任何一个网关都成立。

相关阅读