系統需要統一格式化返回調用異常的錯誤信息,所以編寫了一個配置類實現了ErrorDecoder的接口,然後再@FeignClient的configuration加上了這個配置類,之前用得好好的,突然有一天不生效了,在這裏記錄排查處理過程。
1.首先查看到源碼,feign.SynchronousMethodHandler#executeAndDecode
在1處發起請求之後,如果響應拋出的是IOException則直接返回了,不會調用到3處的自定義異常處理。
2.對於服務沒有啓動的情況,原生的異常類是UnknownHostException,在這裏可能開啓了重試,需要關掉,配置如下
spring:
cloud:
loadbalancer:
retry:
# 關閉自動重試,開啓會導致feign ErrorDecoder配置失效
enabled: false
3.對於接口超時,這裏拋出SocketTimeoutException確實是IOException的子類,不想每個FallbackFactory都加上這段判斷處理邏輯怎麼辦呢,可以使用AOP對這個方法進行切入統一處理
@Slf4j
@Aspect
@Component
public class FeignExceptionAspect {
public FeignExceptionAspect(){}
@Pointcut("execution(* com.hyp.*.api.factory.*.create(..))")
public void pointcut(){}
@Before("pointcut()")
public void before(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
Object obj = args[0];
if (obj == null) {
return;
}
Throwable throwable = (Throwable)obj;
if (throwable instanceof SocketTimeoutException || throwable instanceof RetryableException) {
log.error("接口超時 {}", throwable.getMessage());
throw new ServiceException("接口超時", HttpStatus.REQUEST_TIMEOUT.value());
} else if (throwable instanceof UnknownHostException) {
log.error("服務不可用 {}", throwable.getMessage());
throw new ServiceException("服務不可用", HttpStatus.SERVICE_UNAVAILABLE.value());
}
}
}