Skip to content

L01-10 异常处理与重试 ​

全局中心内容:重试前先问「再试一次结果会不同吗」——不会就别试。 全局讲解主线:AI 错误比普通 HTTP 多在哪 → 一次真实的账单事故 → 建分类器和退避 → 现场模拟各类错误。


P1 · 产出页 ​

中心内容:模型会挂,你的应用不会崩,账单也不会爆。

  • 页面内容

    • 可重试与不可重试分开
    • 限流走指数退避 + 抖动
    • 重试次数与 Token 消耗都进日志
  • 讲解技巧

    • 用数字开场:「有人给所有异常统一重试 3 次,一次两小时的故障多花了 3 万」。
    • 一句话点题:这一节讲的是怎么不让一次失败变成三次失败。
  • 时长:20s


P2 · 错误分类表 ​

中心内容:AI 的错误比调微服务多出一整类。

  • 页面内容

    • 不可重试:401 鉴权 / 400 参数 / 上下文超限 / 内容审核
    • 可重试:429 限流 / 5xx / 超时
    • 灰色:输出截断(要加大 maxTokens 再试)
  • 讲解技巧

    • 逐行问「重试有用吗」,让学员自己答出结论。自己推导的结论记得住。
    • 重点讲「上下文超限」:重试必失败,而且会白白再花一次钱。
  • 时长:3min


P3 · 事故复盘页 ​

中心内容:重试会放大故障,不只是多花钱。

  • 页面内容

    • 10 万次失败 → 40 万次请求
    • 无效重试计入限流统计,延长超限时间
    • 账单 +3 万,恢复时间被自己拖长
  • 讲解技巧

    • 这页是全课最贵的一页,要放慢讲。用时间线方式:0 分钟超限 → 重试介入 → 故障被拉长 → 账单爆炸。
    • 结论钉死:重试是把双刃剑,它会放大故障。所以需要退避、上限、熔断三件套。
  • 时长:3min


P4 · 原理图:重试三要素 ​

中心内容:判定 × 退避 × 上限,缺一不可。

  • 页面内容

    • 只有上限没退避 = 雪崩放大器
    • 只有退避没上限 = 慢请求堆积
    • 三要素齐全才安全
  • 讲解技巧

    • 用「两个缺口的后果」来讲,比正面讲定义更有效。
    • 黑板画一个三角,三个顶点分别是判定、退避、上限。
  • 时长:2min 30s


P5 · 退避策略对比 ​

中心内容:必须加抖动,否则会有重试风暴。

  • 页面内容

    • 固定间隔 → 同时重试,二次冲击
    • 指数退避 → 分散压力
    • 指数 + 抖动(推荐)
    • 遵守 Retry-After(不是所有厂商都返回)
  • 讲解技巧

    • 讲清「重试风暴」:一批被同时限流的请求会同时重试,形成周期性尖峰。画一张尖峰图。
    • 一句话:抖动把重试时间点打散。
  • 时长:2min 30s


P6 · 超时配置 ​

中心内容:读取超时设太短是最常见的配置错误。

  • 页面内容

    • 连接超时 5s
    • 读取超时(关键):普通对话 60s / 长文本 120s / Agent 单步 30s
    • 整体超时:流式必设
  • 讲解技巧

    • 给出具体数字,学员最需要的就是这个。
    • 讲一个现象让学员自查:「如果你发现很多请求在第 5 秒失败,而你设的超时恰好是 5 秒——那不是模型慢,是你配错了」。
  • 时长:2min


P7 · 编码:错误分类器 ​

中心内容:未知错误默认不重试。

  • 页面内容

    • ErrorClassifier.classify(ex)
    • 401/400/context_length/content_filter → FAIL_FAST
    • 429/5xx/超时 → RETRY
    • 其他 → FAIL_FAST
  • 讲解技巧

    • 强调最后那条是刻意设计:面对没见过的错误,保守更安全。这句话体现了工程判断力。
    • 说明为什么按消息匹配而不是异常类型:厂商抛的异常类型不统一,HTTP 状态码更可靠。
  • 时长:5min


P8 · 编码:退避与重试封装 ​

中心内容:重试耗尽要有降级,不能抛异常给用户。

  • 页面内容

    • Backoff.nextDelay(attempt):800ms × 2^n,±30% 抖动,上限 20s
    • 循环内判定 → FAIL_FAST 直接抛
    • 耗尽 → fallback(question)
  • 讲解技巧

    • fallback 的文案要展示出来:「AI 服务暂时不可用,已记录你的问题」。对比「500 Internal Error」,差距一目了然。
    • 强调:降级不是返回空,是给出次优但有用的结果。
  • 时长:5min


P9 · 运行:四类故障模拟 ​

中心内容:401 只有一次调用记录,429 间隔递增。

  • 页面内容

    • fault=auth → 立刻失败,无重试
    • fault=ratelimit → 三次重试,间隔 0.8s / 1.6s,最终降级
    • fault=timeout → 重试后降级
    • fault=context → FAIL_FAST,提示内容过长
  • 讲解技巧

    • 四类必须全部现场跑,尤其是第一类——「只有一次调用记录」是分类器生效的铁证。
    • 用日志时间戳证明退避间隔递增。数字自己会说话。
  • 时长:4min


P10 · 避坑与小结 ​

中心内容:重试会成倍放大成本,必须有账单视角监控。

  • 页面内容

    • 按 conversationId 统计实际调用次数,超「请求数 × 1.3」告警
    • 超时错误谨慎重试:服务端可能已扣费
    • 别吞掉原始异常,首尾两次都要记
  • 讲解技巧

    • 第一条给具体阈值:「请求数 × 1.3」。没有这个监控,重试就是个看不见的吞钱黑洞。
    • 结尾悬念:「厂商持续故障两小时,你的重试会不会把故障拖更久?」——引出 03B-09 熔断。
  • 时长:2min


讲师备忘 ​

项内容
课前必做四类故障开关全部预跑一遍;准备 429 重试的日志时间戳截图
最容易超时处P3 事故复盘,学员会追问细节——控制在 3 分钟,细节写进知识页
学员最常问「为什么不用 Resilience4j?」答:可以用,但异常分类仍要自己做,见知识页等价写法
现场备用真实限流难触发 → 用内置 fault 开关模拟,效果一致