分布式系统java异常处理需分类响应:网络层异常(如connectexception)可重试,业务层异常(如400/503)依错误码决策,非受检异常应前置拦截;须精准捕获具体异常、限制重试边界、保障资源释放与可观测性。

分布式系统中做Java异常处理,不能靠一层try-catch包住远程调用就完事。关键在于分类响应、精准捕获、有节制重试、保障资源释放,并让失败可观察、可干预。
按异常类型分策略处理
远程调用失败不是一种情况,而是三类问题:
-
网络层异常:如
ConnectException、SocketTimeoutException,说明连接不通或响应慢,大概率是瞬时抖动,适合重试 - 业务层异常:比如HTTP返回400(参数错)、409(冲突)、503(服务忙),需解析错误码再决策——“库存不足”不重试,“系统繁忙”可重试
-
非受检运行时异常:如
NullPointerException、IllegalArgumentException,通常是本地参数校验缺失或逻辑缺陷,应在调用前拦截,而不是等抛出来再catch
精准捕获,拒绝Exception通吃
用catch(Exception e)会掩盖真实原因,也破坏重试判断逻辑:
- 对
RestTemplate或FeignClient,优先捕获具体子类:HttpClientErrorException(4xx)、HttpServerErrorException(5xx)、ResourceAccessException(连接/超时) - 多个
catch块注意顺序:子类在前、父类在后,例如先catch(ConnectException),再catch(IOException) - 日志必须记录完整堆栈+上下文:traceId、接口名、入参摘要;避免只打
e.getMessage()或e.printStackTrace()
重试要有边界和依据
盲目循环重试可能压垮下游或引发雪崩:
- 只对明确可恢复的异常重试,比如网络超时;对“订单已取消”“权限拒绝”这类业务确定失败的,直接降级或抛出
- 设最大重试次数(常见为2~3次)和退避策略,推荐指数退避+随机抖动,例如:
100ms → 300ms → 900ms,再加±30%扰动 - 重试必须配合幂等设计:带上唯一
requestId,服务端校验重复请求并去重,避免多次扣款、发券等副作用
绑定任务生命周期,动态调控退避
重试不是静态公式,要随系统状态和业务时效性调整:
- 任务带
deadline字段,每次重试前检查是否超时——过期订单不再重试,避免无效调度 - 高优任务(如支付扣减)允许更多次数、更短延迟;低优任务(如日志归档)限制2次且首次延迟≥2秒
- 当监控发现下游错误率>20%或自身CPU>80%,自动拉长退避间隔,甚至熔断本次重试,防止恶化
不复杂但容易忽略:异常处理的本质,是把“失败”变成一个结构化、可编排、可度量的业务状态,而不是补丁式兜底。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











