从症状出发排障
排障的第一步永远是拿到 z-request-id——它是贯穿客户端、网关、上游、日志的唯一线索。
先拿到 z-request-id
每个请求的响应头里有 z-request-id(格式 <iso8601>-<uuid4>)。客户端报错时,让客户端把响应里的这个头给你。顺手把 z-gateway(格式 <brand>/<version>,如 Protoflux/0.2.1)也拿回来——先确认版本再排查,避免对着一个旧镜像已经修过(或尚未包含)的症状白费功夫。
拿不到响应头时
客户端在收到响应前就失败了(连接被拒、TLS 失败)时没有 z-request-id——这种是网关没收到请求或收到前就断,从网关侧日志查不到,先查网络层(端口、防火墙、反代)。
进控制台 → 日志页,在搜索框粘上这个 ID 即可定位。日志详情含完整请求/响应生命周期,见 导出账单 Excel 与日志排查 的「实战:定位客户端问题」。
客户端报 401 / 403
| 状态码 | error_type 常见值 | 含义 | 处理 |
|---|---|---|---|
| 401 | authentication_error | 没带访问密钥或密钥无效/被禁用 | 检查 Authorization: Bearer 后跟的是你签发的访问密钥(不是上游 sk-...);密钥是否被禁用 |
| 403 | model_access_denied | 密钥所在密钥组的 models 列表没含该模型 | 回密钥组把模型加进去(或 *) |
| 403 | model_access_denied | 密钥组的 load_balancers 没含该 LB | 回密钥组「负载均衡器」子页签勾选(* 不含 LB) |
| 403 | ip_banned | IP 被封禁(连续登录失败触发) | 等几分钟(默认 300 秒)自动解封 |
403 的 LB 维度是最常见的配错点,见 多租户隔离。
客户端报 404
model_not_found:模型名拼错,或该模型被设了hide_name(只能用别名访问)。见 上游与模型字段 的「隐藏主名」。- 别名 vs 规范名:密钥组
models只匹配规范名,不解析别名。 - 完整 404 错误码见 错误码速查;Claude Code 场景的 404 模型名对齐见 Claude Code 经网关接入 → 常见问题。
客户端报 400
| error_type | 成因 | 处理 |
|---|---|---|
bad_request | 请求 JSON 解析失败 / 字段语义校验失败 | 检查请求体 JSON 与必填字段 |
unsupported_feature | 该「客户端协议 → 上游协议」组合没有翻译器 | 查 协议互通矩阵 换协议 |
invalid_request_error(Anthropic 客户端) | 对话历史里 tool_use id 重复 | 去重 tool_use id,见 错误码速查 |
带图片的请求被上游 400 拒收(文本模型收到了带图请求):给模型加一条 switch-route 规则把带图请求改投视觉模型,见 增强模型能力 场景一与 把含图片的请求路由到视觉模型。
客户端报 429
429 有多种来源,体格式与是否带头都不同,先分清是哪种(完整见 错误码速查 → 429 的来源):
| 来源 | 体 / 头特征 | 处理 |
|---|---|---|
| 每访问密钥限流 | JSON 体,带 Retry-After 头 | 该密钥请求过密;分流密钥或降频,必要时在控制台调高密钥/组的 rate_limit(RPM/TPM) |
| 每 IP 限流 | JSON 体,无 Retry-After | 同一 IP 请求过多;调 IP_RATE_LIMIT_RPM |
| 上游限流 | JSON 体,带 Retry-After 头 | 上游本身限流;按 Retry-After 退避重试,或加 key / 加上游分摊 |
| 过载准入(排队深度 / 连接预算 / 内存门) | JSON 体,带 Retry-After 头 | 网关本身健康但在途过载;按 Retry-After 退避重试。持续出现说明容量不足——扩容,或核对 内存准入与溢写、监听与请求限制 各预算配置 |
限流各层的配置见 审计与安全配置 → 限流;内存门触发的 429 与内存水位另见下方「网关内存异常升高」。
客户端报 502 / 503
| 状态码 | 来源 | 处理 |
|---|---|---|
| 502 bad_gateway | 上游不通或返回非预期 | 检查上游 base_url、API key、上游可达性 |
| 503 | 所有节点不可用(LB 重试预算耗尽)/ 网关排空(drain) | LB 场景检查每个 entry 的上游;排空是正常下线 |
| 503 upstream_saturated | 候选上游全部饱和(坏死链接预算满) | 带 Retry-After,按其退避重试;打开控制台 设置 → 系统 的「上游健康」块定位挂死的上游,检查其连通性 |
| 504 outbound_deadline_exceeded | 出站尝试链总时限耗尽 | 上游长时间无首响应;检查该上游连通性与超时配置 |
503 持续不停 = 所有节点都挂,检查每个上游。Bedrock 场景注意填的是 Bedrock API key 不是 IAM key,见 接入 AWS Bedrock。
请求很慢或超时
- 客户端超时但上游正常:检查
UPSTREAM_SEND_TIMEOUT_SECS(发请求体+等响应头,默认 180)/UPSTREAM_READ_TIMEOUT_SECS(单块读,默认 600)。整个上游生命周期还有一道 3600 秒的硬上限(固定,不通过环境变量开放)。见 环境变量配置参考。 - 上游本身就慢(推理模型长思考):调大
UPSTREAM_READ_TIMEOUT_SECS,它每块重置。 - 跨境上游僵尸连接:跨境建议调短反代/上游侧的 keepalive;该 TCP keepalive 参数未通过环境变量开放,有需要请联系支持。
流式中途断掉
- 首块发出后上游断:不换节点,记录
body_incomplete,已收部分返回客户端。 - 网关侧超时:
STREAMING_KEEPALIVE_SECONDS(默认 15)发 SSE:keep-alive,需短于反代空闲超时(Nginx 默认 60)。反代超时太短会切断长流。 - 流式时长或空闲超上限:
MAX_STREAM_DURATION_SECS(默认 3600)是单流总时长上限,STREAM_IDLE_TIMEOUT_SECS(默认 600)是两块间空闲上限,超过即断流。
以上流式相关环境变量(STREAMING_KEEPALIVE_SECONDS / MAX_STREAM_DURATION_SECS / STREAM_IDLE_TIMEOUT_SECS)见 环境变量配置参考 → 流式。
网关内存异常升高
- 大 body 场景用了 after 槽脚本做纯路由决策:改用
switch-route规则。见 脚本性能与内存 的反模式。 max_request_size_mb/max_response_body_mb设得过大:多模态大对话占内存。- 内存门(memory gate)触发 429:调
memory_soft_limit_mb或检查是否有异常大的突发流量。
还定位不了怎么办
常见问题
Q:日志里找不到这个 z-request-id? 可能请求没到网关(网络层断),或在 401 早期失败阶段(未持久化)。检查客户端是否真连到了网关端口。
Q:错误体格式是什么样的? 三种格式(取决于客户端协议与错误阶段),见 错误码速查。
