核心答案:API 报错按「状态码 → 责任方」分流:4xx 是客户端问题(401 未认证、403 无权限、429 请求过频),5xx 是服务端问题(502 上游故障、503 过载、504 超时)。JWT 不过期先本地解码看 exp 字段;SLA 99.9% 对应每月 43.8 分钟停机预算。

状态码决策树

拿到错误码先问三个问题:

  1. 4 开头? → 问题在请求方:参数、认证、权限、频率
  2. 5 开头? → 问题在服务方:重试之前先看对方状态页
  3. 没有状态码(CORS/网络错误)? → 请求根本没到达或响应被浏览器拦截——查控制台详情,不是接口本身坏了

高频状态码速查表

状态码含义第一动作
400请求格式错误对文档逐字段核参数类型
401未认证查 token 是否过期/未带
403无权限查账号权限/scope/IP 白名单
404路径不存在核 URL 拼写与版本前缀
429请求过频指数退避,看 Retry-After
500服务端异常报障,附 trace id
502网关上游故障查上游服务存活
504网关超时查慢查询/超时配置

完整 26 个状态码可用 [HTTP 状态码速查](/c/dev/http-status) 搜索定位。

JWT 三段结构与过期检查

JWT 格式:xxxxx.yyyyy.zzzzz,三段均为 Base64URL 编码:

  • header:算法与类型({"alg":"HS256","typ":"JWT"}
  • payload:用户数据 + 时间声明——exp 过期时间、iat 签发时间、nbf 生效时间(均为 Unix 秒)
  • signature:签名,服务端用密钥对前两段签名

本地排障:把 token 粘进 [JWT 解码器](/c/dev/jwt),header/payload 直接可读,exp 自动换算本地时间并显示剩余有效期。注意:解码 ≠ 验签——任何人都能解码 payload,敏感数据永远不要放进 JWT。

SLA 停机预算对照表

SLA年停机月停机典型场景
99%3.65 天7.3 小时内部工具
99.9%8.77 小时43.8 分钟一般商用
99.95%4.38 小时21.9 分钟电商主站
99.99%52.6 分钟4.38 分钟支付核心
99.999%5.26 分钟26.3 秒运营商级

每加一个 9,停机预算缩 10 倍,架构成本指数上升——多活、自动故障转移是 99.99% 的入场券。

实例:curl 502 排查五步走

现象:curl https://api.example.com/pay 返回 502 Bad Gateway。

  1. 换网络重试(排除本地链路)→ 仍 502
  2. 查服务状态页/群公告 → 无公告
  3. curl -v 看响应头 via/server → 是 nginx 网关发出,说明网关活着、上游应用挂了
  4. 登录网关机 ss -lptn 查上游端口 → 无监听,应用进程崩溃
  5. 看应用日志末行 → OOM killed → 重启+加内存限制+告警

实例:JWT 401 定位

现象:前端调 /api/orders 返回 401。

  1. 解码 token → exp: 1785964800(今天 12:00),当前 14:00 → 过期 2 小时
  2. 但前端有 refresh 逻辑为何没触发?→ refresh 接口也 401
  3. 解码 refresh token → 正常 → 查请求头 → Authorization 拼成了 Bearer 少了空格后的 token(拼接 bug)

工具链:JWT 解码器看时间 → [URL 解析器](/c/dev/url-parser) 核 query 参数是否带错 → 状态码速查确认 401 vs 403 语义。

常见误区

  • 401 当 403 用:401=「你是谁」(没带/过期凭证),403=「知道你是谁,但你没权限」。混用会让前端误判要不要跳登录。
  • 重试 5xx 不设上限:雪崩场景下无退避重试等于 DDoS 自己。正确姿势:指数退避 + 抖动 + 熔断。
  • JWT 里放手机号/身份证:payload 只是 Base64 编码,谁都能解码——JWT 不是加密容器。
  • 「四个 9 随便上」:99.99% 意味着全年只能挂 52 分钟,一次手滑重启就可能花光全年预算;没有多活架构不要承诺。