关键在于精准捕获网关职责内异常:ClientResponseException映射下游错误、TimeoutException返回504、IllegalArgumentException返回400;禁捕Throwable;统一标准化错误响应体;结合Resilience4j重试/熔断/降级;日志结构化且不透传敏感信息。

微服务网关中捕获下游异常并转为友好提示,关键不在“捕获得多”,而在“捕获得准、转化得稳、响应得清”。它不是把所有异常兜住再拼一句“出错了”,而是分层识别、分类映射、统一出口。
只捕获网关职责范围内的可处理异常
网关不处理业务逻辑,只负责路由、协议转换和基础容错。因此应聚焦以下几类明确、可预期的异常:
- ClientResponseException(如 WebClient 返回 4xx/5xx):说明下游已返回错误响应,此时应提取其 status code 和 body,不做重抛,直接映射
- TimeoutException / ReadTimeoutException:网络或下游响应超时,适合标记为“临时不可用”,返回 504 并附带重试建议
- IllegalArgumentException / IllegalStateException:如路由配置缺失、路径参数非法,属网关自身配置或输入问题,应返回 400 + 明确提示(如“请求路径不匹配,请检查 API 地址”)
- 不建议 catch Exception 或 Throwable:会吞掉 OOM、StackOverflowError 等致命错误,导致故障静默,难以监控和恢复
将下游原始错误体标准化为统一响应格式
下游服务可能返回 HTML 错误页、空响应、非 JSON 格式或未按规范填充 code 字段。网关需做兜底清洗:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 若下游返回 4xx/5xx 但响应体为空或非 JSON,网关自动构造标准错误体:
{"code":"GATEWAY_DOWNSTREAM_ERROR","message":"依赖服务返回异常响应","requestId":"xxx","timestamp":1724197200000} - 若下游已返回标准 JSON(含 code/message),优先复用其 code,仅补充网关级字段(如
X-Request-ID、X-Error-Source: "user-service") - 对下游返回的 500 类错误,统一降级为
"code":"SERVICE_UNAVAILABLE",避免暴露内部系统细节
结合 Resilience4j 实现“有策略”的失败反馈
捕获异常只是起点,真正的友好提示来自后续动作是否合理:
立即学习“Java免费学习笔记(深入)”;
- 对偶发性超时或连接异常(如 ConnectException),触发 最多 2 次重试,前端看到的是“稍等,正在重试…”而非立刻报错
- 当下游连续失败达阈值(如 3 次 5xx),熔断器打开,后续请求直接走 fallback —— 返回预设的缓存提示或静态兜底页(如“当前服务繁忙,推荐查看热门内容”)
- fallback 方法本身也需 try-catch 包裹,防止降级逻辑崩溃导致二次 500
日志与可观测性必须结构化
用户看到的提示语要简洁,但后台记录必须完整,否则无法定位根因:
- 每条错误日志必须包含:
requestId、downstreamService、httpStatus、exceptionType、完整堆栈(SLF4J 自动展开 cause 链) - 在 error 日志中附加关键上下文,例如:
log.error("Downstream call failed [{}], service={}, path={}, cost={}ms", requestId, serviceName, uri, duration, ex) - 禁止在响应体中透传
stackTrace、cause或任意原生异常字段;Jackson 全局配置@JsonIgnoreProperties({"stackTrace", "cause", "suppressed"})

















