当单体应用拆分成分布式系统,异常就像被打开的潘多拉魔盒:RPC调用超时、分布式事务雪崩、第三方接口突然罢工…在最近的电商大促中,我们的系统就经历了这样的至暗时刻。本文将用真实代码示例,展示如何构建分布式异常处理体系。
一、全局异常拦截:最后的防线
@RestControllerAdvice
public class GlobalExceptionHandler {// 处理业务异常@ExceptionHandler(BizException.class)public Result handleBizException(BizException e) {log.error("业务异常: {}", e.getErrorMsg());return Result.fail(e.getErrorCode(), e.getErrorMsg());}// 处理Feign调用异常@ExceptionHandler(FeignException.class)public Result handleFeignException(FeignException e) {log.error("服务调用异常: {}", e.contentUTF8());return Result.fail(ErrorCode.SERVICE_UNAVAILABLE);}// 兜底异常处理@ExceptionHandler(Exception.class)public Result handleException(Exception e) {log.error("系统异常: {}", e.getMessage());return Result.fail(ErrorCode.SYSTEM_ERROR);}
}
关键点:通过@ControllerAdvice实现三层防护,特别注意对Feign异常的单独处理,保留原始错误信息
二、服务间调用异常处理
- Feign+Sentinel双保险配置:
feign:client:config:default:connectTimeout: 3000readTimeout: 5000sentinel:scg:fallback:mode: responseresponse-body: '{"code":503,"msg":"服务降级"}'
- 自定义FallbackFactory:
@Component
public class OrderServiceFallbackFactory implements FallbackFactory<OrderServiceClient> {@Overridepublic OrderServiceClient create(Throwable cause) {return new OrderServiceClient() {@Overridepublic Result<OrderDTO> getOrder(String orderId) {if(cause instanceof BizException){return Result.fail(((BizException) cause).getErrorCode(), "订单服务异常");}return Result.fail(ErrorCode.SERVICE_DEGRADE);}};}
}
实战经验:在双十一大促中,这种组合策略帮助我们拦截了70%以上的级联故障
三、分布式事务异常处理
使用Seata的TCC模式示例:
@LocalTCC
public interface OrderTccAction {@TwoPhaseBusinessAction(name = "prepareCreateOrder", commitMethod = "commit", rollbackMethod = "rollback")boolean prepare(BusinessActionContext actionContext,@BusinessActionContextParameter(paramName = "order") Order order);boolean commit(BusinessActionContext actionContext);boolean rollback(BusinessActionContext actionContext);
}
补偿策略:
- 自动重试:对网络抖动等临时性错误
- 人工干预:对数据不一致等严重问题
- 事务日志:记录关键操作节点
四、流量洪峰应对策略
- Resilience4j熔断配置:
CircuitBreakerConfig config = CircuitBreakerConfig.custom().failureRateThreshold(50).waitDurationInOpenState(Duration.ofMillis(1000)).ringBufferSizeInHalfOpenState(2).ringBufferSizeInClosedState(2).build();
- 自适应限流算法:
@Slf4j
public class AdaptiveLimiter {private AtomicInteger currentLimit = new AtomicInteger(100);public boolean tryAcquire() {int current = currentLimit.get();if(current <= 0) return false;// 根据RT和成功率动态调整double successRate = getRecentSuccessRate();long avgRT = getAvgResponseTime();if(successRate < 90% || avgRT > 500ms) {currentLimit.updateAndGet(x -> Math.max(x/2, 10));} else if(successRate > 99% && avgRT < 100ms) {currentLimit.updateAndGet(x -> Math.min(x*2, 1000));}return true;}
}
五、异常追踪三板斧
- 全链路追踪:
@Slf4j
public class TraceInterceptor extends HandlerInterceptorAdapter {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {MDC.put("traceId", UUID.randomUUID().toString());}
}
- 异常画像系统:
@Aspect
@Component
public class ExceptionMonitor {@AfterThrowing(pointcut = "execution(* com..*.*(..))", throwing = "ex")public void monitorException(Exception ex) {ExceptionMetric metric = new ExceptionMetric(ex.getClass().getSimpleName(),Thread.currentThread().getName(),System.currentTimeMillis());KafkaTemplate.send("exception_metrics", metric);}
}
- 智能告警:基于ELK的异常模式识别
总结
在分布式系统中,异常处理不是简单的try-catch,而是需要建立完整的防御体系:
- 全局异常拦截:统一异常出口
- 服务治理:熔断/限流/降级三板斧
- 事务补偿:最终一致性保障
- 智能监控:快速定位问题根源
当系统吞吐量从100TPS提升到5000TPS时,我们的异常处理体系经受住了真实流量的考验。记住:好的异常处理方案,不是消灭异常,而是让系统优雅地与之共处。