错误处理的分层:哪些该抛、哪些该吞、哪些该重试
最常见的两种烂代码:catch 了什么都不做,或者 catch 了只打一行 log 就继续往下走。
错误处理的本质是「决定谁负责」:调用方负责、当前层处理、还是上报给人。
先说结论
能恢复的重试,不能恢复的抛出,用户相关转成友好文案,全部带上上下文。
- 区分「临时故障」与「逻辑错误」
- 重试用指数退避 + 抖动,且限制次数
- 记录错误时带 trace id 与关键参数(脱敏)
- 不吞异常:至少上报
先把问题说清楚
「吞掉异常」是最危险的做法:程序继续跑,但状态已经不对了,问题会在几小时后以另一种形式爆发。
重试也不是万能的:非幂等操作重试可能造成重复扣款。
具体怎么做
按顺序执行,每步都验证完再进下一步:
- 先给错误分类:网络/超时/限流/业务校验/程序 bug
- 对可重试错误加退避重试(最多 3 次)
- 对不可重试错误快速失败,返回明确信息
- 统一记录:时间、trace id、错误码、上下文
- 对用户展示可理解的文案,技术细节进日志
参数与成本对照
把关键数值摊开,方便判断该选哪条路:
| 错误类型 | 处理 | 重试 |
|---|---|---|
| 网络超时 | 重试 + 告警 | 可 |
| 限流 429 | 退避后重试 | 可 |
| 参数校验失败 | 直接返回 | 不可 |
| 空指针/类型错误 | 修复代码 | 不可 |

几个容易踩的坑
下面这些是最常见的错误做法:
- catch(Exception e){} 直接吞掉
- 对所有错误统一重试 3 次:把幂等性问题放大
- 日志只写 e.message 不写堆栈
- 把内部错误信息直接返回给用户
最后补两句
错误处理的目标不是「不报错」,而是「出错时系统状态可预期、人能快速定位」。
工具是手段,理解机制才是能力。命令记不住没关系,知道「该看什么」就够了。
评论 (3)
照着做了一遍,确实少走弯路。第二步最容易漏,建议顺手加个检查清单。
比「一键脚本」有用多了,知道为什么比知道怎么做重要。
补充一句:不同版本行为会变,动手前先确认自己的版本号。
发表评论