面试题答案
一键面试架构设计
- 统一异常类型定义
- 在整个微服务架构中,定义一套通用的异常类型。例如,创建一个基础异常类
BaseException
,然后根据不同业务场景继承它,如BusinessException
用于业务逻辑错误,SystemException
用于系统级错误等。这样不同服务在抛出异常时,有统一的类型体系。
- 在整个微服务架构中,定义一套通用的异常类型。例如,创建一个基础异常类
- 异常传递机制
- HTTP 状态码 + 自定义响应体:在服务间通过 HTTP 进行调用时,利用 HTTP 状态码传递异常的类别,比如 400 表示客户端错误(如参数错误等业务异常),500 表示服务器内部错误(系统异常)。同时,在响应体中自定义结构,包含异常的详细信息,如错误码、错误信息等。例如:
{ "errorCode": "1001", "errorMessage": "参数不能为空" }
- 消息队列(MQ):对于异步调用场景,可利用消息队列传递异常信息。当服务产生异常时,将异常信息封装成消息发送到特定的异常队列,接收方从队列中消费异常消息进行处理。这样可以实现异步解耦,提高系统的整体性能和可扩展性。
- 全局异常处理器
- 在每个微服务内部,设置全局异常处理器。在 Spring Boot 中,可以使用
@ControllerAdvice
和@ExceptionHandler
注解来实现。全局异常处理器捕获所有未处理的异常,将其转换为统一的响应格式,包括上述提到的错误码和错误信息,然后返回给调用方。
- 在每个微服务内部,设置全局异常处理器。在 Spring Boot 中,可以使用
技术选型
- HTTP 客户端
- 对于服务间的 HTTP 调用,可选用
Feign
或RestTemplate
。Feign
集成了 Ribbon 实现负载均衡,并且支持声明式调用,在处理异常方面,可通过自定义ErrorDecoder
来处理服务调用失败时的异常,将响应中的异常信息解析并转换为合适的异常类型。例如:
@Configuration public class FeignConfiguration { @Bean public ErrorDecoder errorDecoder() { return new CustomErrorDecoder(); } } public class CustomErrorDecoder implements ErrorDecoder { @Override public Exception decode(String methodKey, Response response) { // 解析响应体中的异常信息 // 转换为合适的异常类型返回 return new RuntimeException("服务调用失败"); } }
RestTemplate
则相对更为灵活,可通过自定义ResponseErrorHandler
来处理异常。
- 对于服务间的 HTTP 调用,可选用
- 消息队列
- 常用的消息队列如 Kafka、RabbitMQ 都可以满足需求。Kafka 具有高吞吐量、可扩展性强的特点,适合处理大量的异常消息。RabbitMQ 则在可靠性和灵活性方面表现出色,支持多种消息模型。例如在 Spring Boot 中集成 Kafka 处理异常消息,配置
KafkaTemplate
用于发送异常消息,通过@KafkaListener
注解监听异常队列消费消息。
- 常用的消息队列如 Kafka、RabbitMQ 都可以满足需求。Kafka 具有高吞吐量、可扩展性强的特点,适合处理大量的异常消息。RabbitMQ 则在可靠性和灵活性方面表现出色,支持多种消息模型。例如在 Spring Boot 中集成 Kafka 处理异常消息,配置
代码实现
- 定义异常类
public class BaseException extends RuntimeException { private String errorCode; private String errorMessage; public BaseException(String errorCode, String errorMessage) { this.errorCode = errorCode; this.errorMessage = errorMessage; } // getters and setters } public class BusinessException extends BaseException { public BusinessException(String errorCode, String errorMessage) { super(errorCode, errorMessage); } } public class SystemException extends BaseException { public SystemException(String errorCode, String errorMessage) { super(errorCode, errorMessage); } }
- 全局异常处理器
@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(BusinessException.class) @ResponseBody public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException ex) { ErrorResponse errorResponse = new ErrorResponse(ex.getErrorCode(), ex.getErrorMessage()); return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); } @ExceptionHandler(SystemException.class) @ResponseBody public ResponseEntity<ErrorResponse> handleSystemException(SystemException ex) { ErrorResponse errorResponse = new ErrorResponse(ex.getErrorCode(), ex.getErrorMessage()); return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR); } // 其他异常处理 } class ErrorResponse { private String errorCode; private String errorMessage; public ErrorResponse(String errorCode, String errorMessage) { this.errorCode = errorCode; this.errorMessage = errorMessage; } // getters and setters }
- 服务间调用异常处理(以 Feign 为例)
- 在 Feign 客户端接口中,定义服务调用方法。
@FeignClient(name = "target - service", configuration = FeignConfiguration.class) public interface TargetServiceClient { @GetMapping("/api/target - endpoint") String targetMethod(); }
- 然后在业务代码中调用 Feign 客户端方法,并处理可能的异常。
@Service public class MyService { private final TargetServiceClient targetServiceClient; public MyService(TargetServiceClient targetServiceClient) { this.targetServiceClient = targetServiceClient; } public void myMethod() { try { String result = targetServiceClient.targetMethod(); } catch (RuntimeException ex) { // 处理 Feign 调用失败转换后的异常 if (ex instanceof BusinessException) { // 业务异常处理 } else if (ex instanceof SystemException) { // 系统异常处理 } } } }
通过以上架构设计、技术选型和代码实现,可以构建一个统一的异常处理与错误管理方案,在 Spring Boot 微服务架构中实现跨服务边界的异常传递与合理处理,同时兼顾性能和可扩展性。