全局异常处理的核心是让异常携带上下文透传,需定义只读、可扩展的统一异常基类,跨服务自动增强上下文,错误响应收口至extensions.context,并联动日志与追踪系统实现精准可观测。

在复杂微服务链路中做全局异常处理,核心不是“拦住异常”,而是让异常带着上下文一路透传——从最底层的数据库连接超时、HTTP调用失败,到最上层的API响应,每个环节都清楚知道“这是谁的请求、在做什么、卡在哪一步”。靠逐层 try-except 手动加日志或包装异常,既易漏又难维护。真正有效的做法是把上下文注入异常本身,并在链路各关键节点自动补全。
统一异常载体:定义可携带上下文的异常基类
Java 和 Python 都应避免直接抛 RuntimeException 或 Exception。必须自定义异常基类,预留结构化字段:
- 必含字段:trace_id、request_id、service_name、business_key(如 order_id / user_id)、error_code(语义化编码,如 PAY_TIMEOUT_001)
-
只读设计:所有字段声明为
final(Java)或@dataclass(frozen=True)(Python),禁止运行时篡改 - 不污染 message:message 仅作人类可读摘要(如“支付渠道调用超时”),参数值、ID 等全部走独立 getter,便于日志采集器提取
-
强制异常链:构造函数必须接收
cause参数,确保底层原始异常(如SQLException、TimeoutError)不丢失
跨服务边界时自动增强异常上下文
异常最容易丢上下文的地方,就是服务间调用出口(Feign、gRPC client)和服务入口(Controller、Dubbo provider)。这里不能依赖业务代码手动包装:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
出参侧拦截:在 HTTP 客户端封装层(如 Spring Cloud OpenFeign 的
ResponseInterceptor)或 RPC stub 中,捕获原始异常后,立即用当前请求的 MDC 上下文(trace_id、order_id 等)构造领域异常并throw new ServiceException(...) from cause -
入参侧兜底:全局异常处理器(
@ControllerAdvice或 Flask 的errorhandler)不只返回 JSON,还要检查异常是否已含上下文;若缺失,则从当前线程 MDC 或请求头中提取 trace_id、tenant_id 等,动态补全再记录和响应 -
虚拟线程注意:若用 Java 虚拟线程或 Python asyncio,MDC/ContextVar 不会自动继承,需在任务提交前显式拷贝并绑定(如
MDC.setContextMap(parentContext))
全链路结构化透传:extensions.context 是唯一出口
无论 REST、GraphQL 还是 gRPC,错误响应体必须遵守契约,所有上下文只能收口到标准扩展区:
-
REST 响应格式固定:
{"code":"PAY_TIMEOUT_001","message":"支付超时","extensions":{"context":{"trace_id":"xxx","order_id":"ORD-2026...","upstream_service":"wxpay-gateway"}}} -
GraphQL 错误必须走 extensions.context:禁用在
message里拼接变量,敏感字段(如手机号)须脱敏后才允许进extensions.debug_info(仅 debug 模式) -
客户端按语义标签消费:前端或下游服务根据
extensions.context.severity(CRITICAL/ERROR/WARN)决定是否告警;根据upstream_service自动跳转对应服务监控页
日志与追踪系统联动,让上下文真正可用
光有字段没用,得让它们出现在 ELK、Prometheus、SkyWalking 里:
-
日志框架配置提取规则:Logback 或 Log4j2 的 pattern 中显式引用
%X{trace_id}、%X{order_id},确保每行日志自带关键维度 -
OpenTelemetry 自动注入:在异常被捕获点,调用
Span.current().setAttribute("error.order_id", orderId),使上下文进入 trace 数据流 -
告警规则绑定上下文:监控系统配置告警时,不只看 error rate,还要过滤
error_code: PAY_TIMEOUT_*且upstream_service: "alipay-svc"的组合,精准定位渠道问题










