自定义sentinel熔断降级处理方法,blockHandler,block Handler Class,fallback,fallbackClass使用方法和注意事项

  • Post author:
  • Post category:其他



背景条件:

默认情况下sentinel发生限流或熔断是直接抛出异常BlockException然后在浏览器响应这么一句话

可见DefaultBlockExceptionHandler类源码



但在现在的前后端分离开发中,我们一般都会

统一响应格式

,因此这样的返回结果往往是不能满足我们的需求的,因此我们需要自定义sentinel熔断或降级的处理方式

这是我们就需要用到

@SentinelResource

注解

注,默认情况下sentinel只会将controller中的接口作为资源,而Service等其他地方的方法sentinel将不会作为sentinel的资源,我们可以手动在方法上加上@SentinelResource注解将其标注为sentinel的资源


前置知识:

BlockException类,其包含五个子类,分别对应sentinel流控降级规则的授权规则、降级规则、限流规则、热点规则、系统规则 因此

blockHandler()

是专门用来处理

sentinel异常


@SentinelResource注解常用属性介绍


使用方法及注意事项:




.

blockHandler():

使用blockHandler()指定指定发生blockExcption时的处理方法

    @GetMapping("/hello/{id}")
    @SentinelResource(value = "hello",blockHandler = "blockHandlerMethod")
    public Result<String> hello(@PathVariable("id") String id){
        testService.test();
        return new Result<>(200,"操作成功","hello"+id);
    }

    public Result<String> blockHandlerMethod(String id, BlockException e){
        if (e instanceof DegradeException){
            return new Result<>(10000,"操作失败","服务已被降级或熔断");
        }else if(e instanceof FlowException){
            return new Result<>(10000,"操作失败","服务已被限流");

        }else { //可以继续根据blockException的类型,配置对应的返回对象
            return new Result<>();
        }
    }

效果:

限流

降级


使用注意事项:


1.处理方法必须与受保护资源在同一个类中


2.处理方法的修饰符必须为pulbic


3.处理方法的参数列表必须和受保护资源相同,并在最后

加上BlockException e接收异常


4.处理方法的返回值必须和受保护资源相同



二.blockHandlerClass


单独新建一个类用于处理受保护资源的BlockException,相比blockHandler()指定本类中的方法更加的解耦且灵活



使用方法:

处理类及处理方法

public class MyBlockExceptionHandler {
    public static Result<String> blockExceptionHandler(String id, BlockException e) {
        if (e instanceof DegradeException){
            return new Result<>(10000,"操作失败","服务已被降级或熔断---byBlockHandlerClass");
        }else if(e instanceof FlowException){
            return new Result<>(10000,"操作失败","服务已被限流---byBlockHandlerClass");

        }else { //可以继续根据blockException的类型配置对应的返回对象
            return new Result<>(1000,"操作失败","其他类型的BlockException---byBlockHandlerClass");
        }
    }
}

受保护资源上配合


blockHandlerClass(指定处理方法所在的类)






blockHandler(指定处理方法的名字)

两个属性使用

    @GetMapping("/hello/{id}")
    @SentinelResource(value = "hello",blockHandlerClass ={MyBlockExceptionHandler.class},
                                        blockHandler = "blockExceptionHandler")
    public Result<String> hello(@PathVariable("id") String id){
        return new Result<>(200,"操作成功","hello"+id);
    }

效果

限流(流控就不展示了)

使用注意事项:


1.指定处理方法必须是public static的


2.处理方法参数列表及返回值和 blockHandler相同


三、fallback()



注意fallback和blockHandler的区别


1. blockHandler是专门(只)处理sentinel流控降级规则抛出的BlockException


2. 而fallback默认处理所有的异常,其中包括BlockEcxeption(因为BlockException是Exception的子类),也就是说如果我们不配置blockHandler,其抛出BlockEcxeption也将会进入fallback方法中


3. fallback处理的异常可通过@SentinelResource中的exceptionsToIgnore属性排除(

不知道为什么我测试可以排除ArithmeticException,但是排除不了BlockException



4. 如果同时配置了blockHandler和fallback,出现BlockException时将进入BlockHandler方法中处理

示例:为hello资源配置一个fallback方法打印异常类名,并留下一个除0异常

    @GetMapping("/hello/{num}")
    @SentinelResource(value = "hello",fallback = "fallbackMethod")
    public Result<String> hello(@PathVariable("num") Integer num){
        int result = 100/num;
        return new Result<>(200,"操作成功","hello"+result);
    }

    public Result<String> fallbackMethod (Integer num,Throwable e){
        return new Result<>(10000,"操作失败","出现"+e.getClass().getSimpleName()+"异常,进入指定的fallback方法");
    }

当我们参数输入0,抛出除0异常

当我们为hello资源进行限流,触发BlockException异常,可以看到依旧会进入我们的fallback方法


使用注意事项:


1.方法必须和被保护资源处于同一个类


2.方法参数列表和受保护资源一致(

可选

是否在最后添加一个Throwable类型参数接收异常,注意类型必须是Throwable)


3.方法返回值必须和受保护资源相同


四、


fallbackClass

该属性类似于上面介绍的

blockHandlerClass,也是为了实现灵活应用及解耦


新建fallback类及方法

public class MyFallbackHandler {
    public static Result<String> fallbackMethod (Integer num, Throwable e){
        return new Result<>(10000,"操作失败","出现"+e.getClass().getSimpleName()+"异常," +
                "                                                  进入指定的fallback方法--byMyFallBackClass");
    }
}

配合fallback()属性指定位于其他类的fallback方法

    @GetMapping("/hello/{num}")
    @SentinelResource(value = "hello",fallbackClass = {MyFallbackHandler.class},fallback = "fallbackMethod")
    public Result<String> hello(@PathVariable("num") Integer num){
        int result = 100/num;
        return new Result<>(200,"操作成功","hello"+result);
    }

效果:

除0

限流

使用注意事项:


1.指定处理方法必须是public static的


2.处理方法参数列表及返回值等和 fallback相同



五、defaultFallback


使用方法和fallback相同,优先级低于fallback,同时配置fallback和defaultFallback时由fallback生效



版权声明:本文为taolin0原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。