核心是错误码贯穿全链路:统一注册中心管理、异常与文案分离、结构化透传、日志链路绑定。所有服务从Nacos加载YAML错误码元数据,启动构建ErrorCodeRegistry;抛BusinessException("USER_NOT_FOUND"),@ControllerAdvice按Accept-Language动态渲染message;Feign自定义ErrorDecoder将code转ApiBusinessException;MDC写入err_code实现日志与链路归因。

核心是让错误码贯穿请求全链路,不被中间层吞掉、不靠字符串匹配、不依赖HTTP状态码硬编码。
统一错误码注册中心
所有微服务不各自定义 ErrorCode 类,而是从同一配置源加载元数据。用 Nacos 或 Spring Cloud Config 管理 YAML 格式错误码:
- USER_NOT_FOUND: { code: 404001, zh: "用户不存在", en: "User not found", httpStatus: 404 }
- 服务启动时加载并构建内存缓存的
ErrorCodeRegistry,提供getByCode("USER_NOT_FOUND")方法 - 业务代码用
@ErrorCode("USER_NOT_FOUND")注解或工具类获取,避免手写字符串字面量
异常构造与拦截解耦
错误码和提示文案必须分离,异常对象只持错误码标识,不拼接语言文案:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 抛出
BusinessException("USER_NOT_FOUND"),而非BusinessException("用户不存在") - 全局
@ControllerAdvice拦截后,根据请求头Accept-Language动态查ErrorCodeRegistry获取对应语言文案 - 响应体固定结构:
{"code": "USER_NOT_FOUND", "httpCode": 404, "message": "用户不存在", "timestamp": "..."}
跨服务调用时透传错误语义
Feign/gRPC 调用不能靠 HTTP 状态码传递业务含义,否则下游无法区分“用户不存在”和“数据库连不上”:
- 下游服务返回 200 状态码 + 结构化错误体(含
code字段),避免触发 Feign 默认的非200异常处理逻辑 - 上游 Feign Client 配置自定义
ErrorDecoder,识别code != 0并转为ApiBusinessException(继承 RuntimeException) - 调用方直接
try-catch ApiBusinessException,通过getCode()提取原始错误码,无需解析 JSON 或字符串
日志与链路中绑定错误码
错误码要随 traceID 一起落库、上报监控,才能实现快速归因:
- 在全局异常处理器中,将
errorCode写入 MDC(如MDC.put("err_code", ex.getErrorCode())) - 日志模板包含
%X{traceId} %X{err_code},确保每条错误日志可关联链路和语义 - 告警规则基于
err_code聚合,比如连续5次出现ORDER_TIMEOUT自动触发工单

















