spring boot 的全局异常处理无法直接捕获服务网格(service mesh)产生的网络层异常,因为服务网格的流量拦截发生在应用进程之外。要实现这一目标,必须将服务网格侧车(sidecar)代理抛出的错误转换为 spring mvc 或 webflux 能识别的标准 http 响应码,或者在网关/入口层统一处理这些错误。

@RestControllerAdvice 能捕获哪些具体的异常类型
全局异常处理器只能捕获由 Java 虚拟机内部逻辑、业务代码或框架自身抛出的异常。对于服务网格而言,如果 Sidecar 代理(如 Envoy)配置了重试或超时策略,它会在应用内部表现为 java.net.SocketTimeoutException 或 ConnectException;如果代理直接拦截并返回错误,则不会进入应用线程,而是直接中断连接。

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.net.ConnectException;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ConnectException.class)
public void handleConnectionError(ConnectException e) {
// 这里可以捕获到服务网格代理因拒绝连接而抛出的异常
System.out.println("Caught: " + e.getMessage());
}
}
如何区分服务网格主动拦截与应用内部报错
区分两者的关键在于异常的来源和堆栈信息。服务网格主动拦截通常表现为连接被重置(RST)或特定的代理错误码,而应用内部报错则是明确的业务逻辑异常。通过检查异常消息中是否包含代理特有的标识,可以在日志中明确区分这两类问题。

import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class MeshExceptionHandler {
@ExceptionHandler(ResourceAccessException.class)
public void handleMeshError(ResourceAccessException e) {
// 检查是否是服务网格代理返回的错误
if (e.getMessage().contains("upstream connect error") ||
e.getMessage().contains("no healthy upstream")) {
System.out.println("Service Mesh intercepted the request");
} else {
System.out.println("Internal application error");
}
}
}
当服务网格返回特定 HTTP 状态码时如何处理
如果服务网格配置为直接返回 HTTP 503 或 4xx 状态码而不抛出异常,全局异常处理器将无法捕获它们,因为这些被视为正常的 HTTP 响应。此时,需要结合自定义的 HandlerExceptionResolver 或使用过滤器来统一处理这些状态码对应的业务逻辑。











