设计思路
- 集中化管理:在微服务架构中,创建一个统一的异常处理组件或模块,负责捕获和处理来自各个微服务的异常。这样可以确保异常处理逻辑的一致性和可维护性。
- 异常分类:对异常进行分类,例如业务异常、系统异常、网络异常等。不同类型的异常可以有不同的处理方式,以便更好地向用户提供针对性的错误提示。
- 日志记录:在异常处理过程中,详细记录异常信息,包括异常类型、堆栈跟踪、发生时间等,以便于调试和故障排查。
- 用户友好提示:将系统内部的异常转换为用户能够理解的友好错误提示。避免向用户暴露敏感的技术细节,同时提供一些引导信息,帮助用户解决问题或联系支持人员。
- 跨服务异常传播:当微服务之间发生调用时,需要设计一种机制来传播异常,确保异常能够在调用链中正确传递并得到处理。
关键实现要点
- 全局异常处理器:在Spring Boot等框架中,可以使用
@ControllerAdvice
注解创建全局异常处理器,捕获控制器层抛出的异常。对于非Web微服务,可以通过自定义的异常过滤器来实现类似功能。
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(BusinessException.class)
public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException ex) {
ErrorResponse errorResponse = new ErrorResponse(HttpStatus.BAD_REQUEST.value(), ex.getMessage(), "Please check your input.");
return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(SystemException.class)
public ResponseEntity<ErrorResponse> handleSystemException(SystemException ex) {
ErrorResponse errorResponse = new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), "System error occurred.", "Please try again later or contact support.");
return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
- 自定义异常类:根据异常分类,定义自定义的异常类,继承自
Exception
或RuntimeException
。这样可以在代码中更清晰地抛出和捕获特定类型的异常。
public class BusinessException extends RuntimeException {
public BusinessException(String message) {
super(message);
}
}
public class SystemException extends RuntimeException {
public SystemException(String message) {
super(message);
}
}
- 错误响应格式:定义统一的错误响应格式,包含错误码、错误信息和用户引导信息。这样可以确保在不同微服务之间返回的错误响应具有一致性。
public class ErrorResponse {
private int errorCode;
private String errorMessage;
private String userGuide;
public ErrorResponse(int errorCode, String errorMessage, String userGuide) {
this.errorCode = errorCode;
this.errorMessage = errorMessage;
this.userGuide = userGuide;
}
// getters and setters
}
- 跨服务异常传播:在微服务之间调用时,可以通过HTTP状态码、自定义头信息或消息队列等方式传递异常信息。例如,在HTTP调用中,可以将异常信息封装在响应体中,同时设置合适的HTTP状态码。
RestTemplate restTemplate = new RestTemplate();
try {
ResponseEntity<String> response = restTemplate.getForEntity("http://microservice2/api/data", String.class);
// handle normal response
} catch (RestClientException ex) {
if (ex instanceof HttpClientErrorException) {
HttpClientErrorException httpEx = (HttpClientErrorException) ex;
ErrorResponse errorResponse = httpEx.getResponseBodyAs(ErrorResponse.class);
// handle business exception from microservice2
} else if (ex instanceof HttpServerErrorException) {
HttpServerErrorException httpEx = (HttpServerErrorException) ex;
ErrorResponse errorResponse = httpEx.getResponseBodyAs(ErrorResponse.class);
// handle system exception from microservice2
} else {
// handle other network or client-side errors
}
}
- 日志记录:使用日志框架(如Log4j、SLF4J)记录异常信息。在异常处理器中,通过日志记录详细的异常堆栈信息,方便开发人员定位问题。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleException(Exception ex) {
logger.error("An unexpected error occurred", ex);
ErrorResponse errorResponse = new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), "An unexpected error occurred.", "Please try again later or contact support.");
return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}