错误处理的分层:哪些该抛、哪些该吞、哪些该重试

开发 · 2 分钟阅读· 217 次阅读

最常见的两种烂代码:catch 了什么都不做,或者 catch 了只打一行 log 就继续往下走。

错误处理的本质是「决定谁负责」:调用方负责、当前层处理、还是上报给人。

先说结论

能恢复的重试,不能恢复的抛出,用户相关转成友好文案,全部带上上下文。

  • 区分「临时故障」与「逻辑错误」
  • 重试用指数退避 + 抖动,且限制次数
  • 记录错误时带 trace id 与关键参数(脱敏)
  • 不吞异常:至少上报

先把问题说清楚

「吞掉异常」是最危险的做法:程序继续跑,但状态已经不对了,问题会在几小时后以另一种形式爆发。

重试也不是万能的:非幂等操作重试可能造成重复扣款。

具体怎么做

按顺序执行,每步都验证完再进下一步:

  • 先给错误分类:网络/超时/限流/业务校验/程序 bug
  • 对可重试错误加退避重试(最多 3 次)
  • 对不可重试错误快速失败,返回明确信息
  • 统一记录:时间、trace id、错误码、上下文
  • 对用户展示可理解的文案,技术细节进日志

参数与成本对照

把关键数值摊开,方便判断该选哪条路:

错误类型 处理 重试
网络超时 重试 + 告警 可
限流 429 退避后重试 可
参数校验失败 直接返回 不可
空指针/类型错误 修复代码 不可

错误处理的分层

几个容易踩的坑

下面这些是最常见的错误做法:

  • catch(Exception e){} 直接吞掉
  • 对所有错误统一重试 3 次:把幂等性问题放大
  • 日志只写 e.message 不写堆栈
  • 把内部错误信息直接返回给用户

最后补两句

错误处理的目标不是「不报错」,而是「出错时系统状态可预期、人能快速定位」。

工具是手段,理解机制才是能力。命令记不住没关系,知道「该看什么」就够了。

评论 (3)

阿
阿哲

照着做了一遍,确实少走弯路。第二步最容易漏,建议顺手加个检查清单。

南
南风

比「一键脚本」有用多了,知道为什么比知道怎么做重要。

K
Kevin

补充一句:不同版本行为会变,动手前先确认自己的版本号。

发表评论

验证码

提交后需站长审核,通过后才会显示。