SpringCloud的异常处理体系--Fegin调用(二)

前言:

在SpringCloud微服务架构中,服务之间的调用一般通过Fegin完成。Fegin使用方式有点类似于Dubbo接口式调用,使用非常简单便捷。Fegin中集成Hystrix熔断器的功能,可以有效预防服务雪崩的出现。Feign中还集成Ribbon,支持负载均衡,模式轮询方式。在Fegin实现服务之间调用时也会遇到异常的问题,这篇文章,我们就来说一下使用Fegin实现服务之间调用的异常处理。

正文:

首先,我们分析一下那几部分会出现异常:服务生产者的异常,服务消费者的异常,Feign的异常。接下来我们说一说每个部分出现异常的处理思路。

服务生产者的异常:

生产者出现异常在这里有两种处理方式:一是利用全局异常器处理异常,将所有异常都封装到Result类中返回给服务的消费者,消费者根据Result类的信息处理异常;二是生产者不处理异常,将异常上抛给Feign的Hystrix熔断器,让熔断器去处理异常,然后把异常信息反馈给消费者。

方式一:可以全局处理器可以参照《SpringCloud的异常处理体系(一)》。

方式二:这里就需要重写Feign的错误解码器(ErrorDecoder)。原因是Feign会将生产者出现的异常都封装成feign.FeignException类型异常上抛给Hystrix熔断器。这样Hystrix拿不到真正的异常类型,无法做出正确的判断。Feign获取的异常信息举例如下:

{"timestamp":1602770868665,"status":500,"error":"Internal Server Error","exception":"com.hanxiaozhang.exception.InternalServerException","message":"系统繁忙,请稍后重试","path":"/order/1"}

基于以上原因,我们应该重写Feign的错误解码器,我想到的方法是利用反射机制,把Feign异常解析成原本的异常,具体的操作如下:

/**
 * 〈一句话功能简述〉<br>
 * 〈FeignClient异常解码器〉
 *  原理:利用反射机制,把Feign异常解析成原本的异常,
 *  不然Hystrix拿到都是feign.FeignException类型异常
 *
 * @author hanxinghua
 * @create 2020/7/30
 * @since 1.0.0
 */
@Slf4j
@Configuration
public class FeignClientErrorDecoder implements feign.codec.ErrorDecoder {

    @Override
    public Exception decode(String methodKey, Response response) {
        String className = null;
        String message = null;
        try {
            String errorContent = Util.toString(response.body().asReader());
            Map<String, String> map = JsonUtil.jsonToMapSS(errorContent);
            if (map == null || map.isEmpty() ||
                    StringUtil.isBlank(className = map.get("exception"))) {
                return new NoFeignDefinitionException();
            }
            message = map.get("message");
            return (Exception) Class.forName(className)
                    .getConstructor(String.class).newInstance(message);
        } catch (Exception e) {
            log.error("FeignClientErrorDecoder-decode异常,异常信息:[{}]",e);
            return new NoFeignDefinitionException(message==null?e.getMessage():message);
        }
    }

}

 Feign的错误解码器把异常解析成原本的异常后,我们在Hystrix熔断器中就可以使用instanceof关键字判断异常类型,对不同的异常进行封装,返回合适Result类信息的给消费者。

 服务消费者的异常:

消费者出现异常,我采取的方法是使用全局异常处理器捕获异常,把异常分装到Result类,返回给用户,具体实现可以参照《SpringCloud的异常处理体系(一)》。这里还有一个小提示,在消费者控制器中(Controller),Result类泛型类可以不指定类型,因为消费者控制器直接面对前端页面,前端接受的是字符串(一般是JSON),没有类型的概念,这样可以减少一些强制转换。举例如下:

public Result<OrderDTO> listByUser(@RequestBody QueryEntity query) { ... }

写成这样: 

public Result listByUser(@RequestBody QueryEntity query) { ... }

 Feign的异常:

 Feign出现异常,也会被Hystrix熔断器处理,这里我们在熔断器中进行判断即可。初次使用可能会遇到“Hystrix首次请求失败超时的异常”,原因是Hystrix默认的超时时间是1s,如果在1s内得不到响应,就进入fallback逻辑。由于Spring使用的懒加载机制,首次请求往往会 比较慢,因此在某些机器(特别是低配的机器)上,首次请求需要的时间可能就会大于1s。我的解决它的方法是在Yaml文件配置延长Hystrix的超时时间,具体配置如下:

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000 # 单位ms

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hanxiaozhang2018

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值