Sentinel集成Feign调用之fallback中小小的经验

前两天看了下Sentinel(分布式系统的流量防卫兵)。网上各种吹捧说简单、开箱即用。然后研究一下,嗯......确实开箱即用,而且上手简单。然后话不多说,立马整一套环境,集成Nacos、Feign上来就是干!但是中间还是遇到了一些问题,先说下我的细节场景:

  1. 我定义了一个服务者(provider)并且提供了Feign客户端调用。

  2. 在服务熔断的Feign客户端实现类中抛出了异常。如下图:

    Feign客户端接口:

    image-20200408102643874

    Feign实现类(自定义fallback函数):

    image-20200408102815763
  3. 我在消费端(consumer)配置了全局异常处理器,然后调用服务端的Feign接口。可是在出现服务熔断即服务端down机的时候,我的消费端总是捕捉不到我自定义的这个ServiceException异常.

    看下我的全局异常处理器

    image-20200408103559842

经过冥思苦想,然后跟踪Sentinel源码终于找到了问题原因。并且总结出经验:

  1. Feign的接口调用端的自定义fallback函数中尽量避免抛出异常。

下面说下为什么我们尽量避免在自定义的fallback中抛出异常

  1. 当使用Fegin接口远程调用服务者出现异常情况的时候,会走fallback中的逻辑。

  2. 我们模拟服务端down机。:

    1. 我们先看下SentinelInvocationHandler 这个类的这段代码。

      image-20200403111125263

      如果 我们的服务端没响应或者网络延迟或者其他未知情况导致methodHandler.invoker() 方法没有正确返回,则抛出异常。也就是调用FeignClient过程中出现了异常。如果我们自定义了服务熔断的fallback方法,则会执行我们的fallback方法。

      下图是模拟服务者down掉的情况,进入到 catch 代码段,校验我们有没有自定义的falback逻辑,有的话则执行

      image-20200403112827715

      执行到我们自定义的fallback逻辑。然后我写的是依然抛出异常,打算交给全局异常处理器处理:

      image-20200403113616410

      此时如果在fallback中依然抛出异常的话。SentinelInvocationHandler 这个类会把这个异常当成一个Error抛出。

      此时我的全局异常处理器就不能把这个异常当做我们自定义的ServiceException处理,而是把它当成了Throwable处理。这样会导致我们排错的时候找错方向,因为我明明抛出的是ServiceException怎么最后变成Throwable了?。

      image-20200403114733501

总结:

  1. Sentinel集成Feign调用的时候,在服务熔断的fallback中尽量避免抛出异常,最后会被Sentinel当做一个Throwable处理。最好正确返回一个我们可识别的一个结果,在返回结果中表明调用异常即可。
  2. 使用Sentinel写个demo很简单。但是企业中使用Sentinel还是需要自己对源码进行一些调整的。
    1. 比如集成Nacos实现持久化的时候。这儿也有个坑,可能是Sentinel的bug。简单说下吧就是当在Sentinel控制台添加流控规则并且持久化到Nacos中去的时候,只能添加一个资源,再次添加资源的时候会把上一个覆盖掉。准备在issues上提一下
  3. 想要在企业中使用Sentinel我感觉必须得把源码拉下来,跑一下。

猜你喜欢

转载自juejin.im/post/5e8d432d6fb9a03c677e64d0
今日推荐