分布式系统中应传递语义明确的错误码而非异常对象,统一定义前缀+三位数字的业务错误码体系,配套元数据,并在响应体中显式携带;服务端通过全局异常处理器或注解映射异常为错误码;客户端按错误码分类处理。

在分布式系统中,Java 的异常本身不能跨进程传递,所以不能直接把本地抛出的 Exception 对象“扔”给远程服务。真正需要传递的是**语义明确、可识别、可翻译的错误码(error code)**,配合消息体(如 JSON、Protobuf)一起传输。关键不是“传递异常”,而是“约定并传递结构化错误信息”。
统一定义业务错误码体系
所有服务共用一套错误码规范,比如:
-
格式建议:前缀 + 三位数字(如
USER_001表示用户不存在,ORDER_002表示库存不足) -
分级管理:按模块划分命名空间,避免冲突;保留通用码(如
SYSTEM_500表示内部错误) - 配套元数据:每个错误码关联默认提示语、HTTP 状态码、是否可重试、日志级别等,存于配置中心或常量类
在 RPC 或 HTTP 接口层注入错误码
不依赖异常对象传播,而是在响应体中显式携带错误码:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
REST API:返回标准 JSON 结构,例如:
{ "code": "USER_001", "message": "用户不存在", "data": null } -
gRPC:使用自定义 status detail(
io.grpc.StatusRuntimeException+Status.Code+ 自定义ErrorCode字段) -
Dubbo:通过
Result包装,或扩展Attachment传 error code,但更推荐放在响应 VO 内部
服务端异常 → 错误码的映射策略
避免在每处 catch 里硬编码转换,推荐集中处理:
立即学习“Java免费学习笔记(深入)”;
-
全局异常处理器(如 Spring 的
@ControllerAdvice):捕获特定异常类型,映射为预定义错误码并封装响应 -
异常与错误码绑定注解:自定义注解
@ErrorCode("USER_001")标在异常类上,运行时自动提取 -
拒绝使用
Exception.getMessage()直接当提示语:它可能含敏感信息或堆栈,应只用预设的国际化 message
客户端解析并还原语义
调用方收到响应后,不判断异常类型,而是解析 code 字段做分支处理:
- 根据错误码决定是否重试(如
NETWORK_TIMEOUT可重试,USER_001不重试) - 前端展示对应友好提示(通过 i18n key 查找文案)
- 日志记录时同时打 error code 和 traceId,便于问题定位
- 避免客户端 switch-case 所有错误码 —— 应按类别分组处理(如“用户类错误”、“系统类错误”)

















