阿里限流神器Sentinel夺命连环 17 问? (7)

blockHandler: 对应处理 BlockException 的函数名称。blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。blockHandler 函数默认需要和原方法在同一个类中。

blockHandlerClass:指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。

官方文档:https://github.com/alibaba/Sentinel/wiki/注解支持

使用@SentinelResource注解自定义一个限流异常返回信息,先自定义一个资源,指定兜底方法为handler,代码如下:

阿里限流神器Sentinel夺命连环 17 问?

第二步:写个对应得兜底方法,必须在同一个类中,代码如下:

阿里限流神器Sentinel夺命连环 17 问?

第三步:对资源QueryOrder新增一个限流规则,如下图:

阿里限流神器Sentinel夺命连环 17 问?

第四步:写个controller,代码就不晒了,自己写吧,哈哈。。。。

第五步:调用接口,疯狂点击,将会出现兜底方法中定义的返回信息,如下图:

阿里限流神器Sentinel夺命连环 17 问?

到这儿基本算是成功了,但是有个问题:兜底方法必须要和业务方法放在同一个类中,这样代码耦合度不是很高吗?

@SentinelResource提供一个属性blockHandlerClass,完美的解决了这一个问题,能够将兜底方法单独放在一个类中,下面来介绍一下。

第一步:新建一个单独的类CommonHandler来放置兜底方法,代码如下:

阿里限流神器Sentinel夺命连环 17 问?

第二步:在@SentinelResource注解中指定blockHandlerClass为上面的类,blockHandler指定兜底方法名,代码如下:

阿里限流神器Sentinel夺命连环 17 问?

好了,至此就完成了,自己照着试试吧.......

上述源码在sentinel-openfeign-provider9009这个模块中,源码获取方式见文末。

12、如何对异常进行降级处理?

程序员每天都在制造BUG,没有完美的代码,也没有完美的程序员,针对代码的运行时异常我们无法避免,但是我们可以当出现异常的时候进行捕获并做出相应的处理,我们称之为降级处理。

异常的降级还是要用到@SentinelResource注解,其中相关的几个属性如下:

fallback:fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求:

返回值类型必须与原函数返回值类型一致;

方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。

fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象

fallbackClass:指定对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。

defaultFallback(since 1.6.0):默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。defaultFallback 函数签名要求:

返回值类型必须与原函数返回值类型一致;

方法参数列表需要为空,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。

defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。

exceptionsToIgnore(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。

1.8.0 版本开始,defaultFallback 支持在类级别进行配置。

注:1.6.0 之前的版本 fallback 函数只针对降级异常(DegradeException)进行处理,不能针对业务异常进行处理

官方文档:https://github.com/alibaba/Sentinel/wiki/注解支持

下面定义一个创建订单的接口,手动制造一个1/0异常,代码如下:

阿里限流神器Sentinel夺命连环 17 问?

上述接口并没有进行异常降级处理,因此调用该接口直接返回了异常信息,非常不友好,如下图:

阿里限流神器Sentinel夺命连环 17 问?

我们可以使用fallback指定异常降级的兜底方法,此时业务方法改造如下:

阿里限流神器Sentinel夺命连环 17 问?

使用fallbackClass属性指定单独一个类处理异常降级,降低了代码的耦合度,fallback属性指定了降级兜底的方法,代码如下:

阿里限流神器Sentinel夺命连环 17 问?

此时再次访问接口,虽然有异常,但是返回的确实降级兜底方法中的返回信息,如下图:

阿里限流神器Sentinel夺命连环 17 问?

到了这里基本满足了异常降级的处理需求,但是仍然有个疑问:能否只用一个方法处理全部的异常?

答案是:必须能,此时就要用到defaultFallback 这个属性了,指定默认的降级兜底方法,此时的业务方法变成如下代码:

阿里限流神器Sentinel夺命连环 17 问?

defaultFallback属性指定了默认的降级兜底方法,这个方法代码如下:

阿里限流神器Sentinel夺命连环 17 问?

好了,异常降级处理到这儿已经介绍完了,但是仍然有一个问题:若 blockHandler 和 fallback 都进行了配置,那么哪个会生效?

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzzxyf.html