七、Sentinel的注解@SentinelResource详细介绍

文章目录

    • @SentinelResource 注解
      • 自定义限流处理逻辑
      • 具体逻辑
        • fallback函数
        • 同时配置blockHandler和fallback属性
        • exceptionsToIgnore属性


@SentinelResource 注解

Sentinel 提供了 @SentinelResource 注解用于定义资源,并提供了 AspectJ (切面)的扩展用于自动定义资源、处理 BlockException 等。

注意:注解方式埋点不支持 private 方法。

@SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。 @SentinelResource 注解包含以下属性:

  • value:资源名称,必需项(不能为空)

  • entryType:entry 类型,可选项(默认为 EntryType.OUT

    资源调用的流量类型,是入口流量(EntryType.IN)还是出口流量(EntryType.OUT),注意系统规则只对 IN 生效

    /**
     * @return the entry type (inbound or outbound), outbound by default
     */
    EntryType entryType() default EntryType.OUT;
    

    为了验证,添加如下两个接口,并配置系统入口流量限流规则:

    @GetMapping("/out")
    @SentinelResource(value = "entryTypeOut", entryType = EntryType.OUT)
    public String entryTypeOut() {
        return "sentinelResource-out";
    }
    
    @GetMapping("/in")
    @SentinelResource(value = "entryTypeIn", entryType = EntryType.IN)
    public String entryTypeIn() {
        return "sentinelResource-in";
    }
    

    新增系统规则:

七、Sentinel的注解@SentinelResource详细介绍_第1张图片

   此时查看实时监控面板,可以看出/in的通过的QPS为1,/out的入口通过的QPS为2,所以系统规则对/in是生效的

七、Sentinel的注解@SentinelResource详细介绍_第2张图片

  • blockHandler / blockHandlerClass: blockHandler 对应处理 BlockException 的函数名称,可选项。blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。

  • fallback:fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了exceptionsToIgnore

    里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求:

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

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

      @GetMapping("/fallback/{id}")
      //添加SentinelResource注解的fallback属性,同时设置方法来解决Java异常
      @SentinelResource(value = "fallback", fallback = "fallbackHandler")
      public String fallback(@PathVariable Long id){
          return "success";
      }
      
      //保证方法签名与原方法一致或加一个 Throwable 类型的参数
      public String fallbackHandler(Long id, Throwable e) {
          xxxxx
      }
      
      // 或者
       public String fallbackHandler(Long id) {
          xxxxx
       }
      
    • fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。

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

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

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

      public String defaultFallbackHandle(Throwable ex){
      	xxxxx
      }
      // 或者
      public String defaultFallbackHandle(){
      	xxxxx
      }
      
    • defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。

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

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

特别地,若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。若未配置 blockHandlerfallbackdefaultFallback,则被限流降级时会将 BlockException 直接抛出

自定义限流处理逻辑

其实我们在使用@SentinelResource注解这两种方案的时候,会出现一些问题:

  1. 没有体现我们自己的业务要求。
  2. 自定义处理方法和业务代码耦合在一起。
  3. 每个业务方法都添加一个限流处理方法,代码将会加剧膨胀。
  4. 无法实现统一全局处理。

解决:@SentinelResource除了blockHandler可以设置自定义限流处理逻辑方法以外,还提供另外一个属性来设置限流处理逻辑类型blockHandlerClass属性,此属性中设置的方法必需为 static 函数,否则无法解析。

具体逻辑

第一步

创建CustomerBlockHandler类型用于处理自定义限流处理逻辑,首先创建myhandler.CustomerBlockHandler

/**
 * 此类型用来处理限流自定义逻辑
 */
public class CustomerBlockHandler {
    public static String handlerException1(BlockException exception){
        return "handlerException1:系统异常,请稍后重试!";
    }
    public static String handlerException2(BlockException exception){
        return "handlerException2:网络崩溃了,请稍后重试!";
    }
}

第二步

我们在SentinelResourceTestController类型中添加一个接口方法,同时设置@SentinelResource注解和blockHandlerClass属性对应的类型和这个类型中对应的处理方法

/**
     * 此方法用到了自定义限流处理类型CustomerBlockHandler
     * 中的handlerException1方法来处理限流逻辑。
     */
@GetMapping("/byCustomer")
@SentinelResource(value = "byCustomer",
                  blockHandlerClass = CustomerBlockHandler.class,
                  blockHandler = "handlerException1")
public String byCustomer(){
    return "-----byCustomer";
}

第三步

测试:给byCustomer资源添加限流规则,然后来测试在超过限流阈值时处理方法是否为CustomerBlockHandler中handlerException1来进行处理。

七、Sentinel的注解@SentinelResource详细介绍_第3张图片

流控效果:

七、Sentinel的注解@SentinelResource详细介绍_第4张图片

fallback函数

(定义如上)

注意: fallback属性和blockHandler属性的本质不同在于他们作用的异常不同

  • blockHandler:针对违反Sentinel控制台配置规则时触发BlockException异常时对应处理的属性
  • fallback:针对Java本身出现的异常进行处理的对应属性。
@GetMapping("/fallback/{id}")
//添加SentinelResource注解的fallback属性,同时设置方法来解决Java异常
@SentinelResource(value = "fallback", fallback = "fallbackHandler")
public String fallback(@PathVariable Long id){
    if (id < 0 || id > 3) {
        throw new NullPointerException("无对应的记录");
    }
    return "success";
}

//保证方法签名与原方法一致或加一个 Throwable 类型的参数
public String fallbackHandler(Long id, Throwable e) {
    return "出现未知的记录";
}

效果(未加流控规则前):

七、Sentinel的注解@SentinelResource详细介绍_第5张图片

然后,我们添加流控规则:

七、Sentinel的注解@SentinelResource详细介绍_第6张图片

F5刷新,这时地效果为:
七、Sentinel的注解@SentinelResource详细介绍_第7张图片

总结:

fallback定义的函数方法,抛出了任何异常,都会触发指定函数的执行。(除了exceptionsToIgnore 里面排除掉的异常类型)
在触发定义的流控规则后,Sentinel会自动抛出BlockException异常。只有fallback存在,没有定义blockHandler时,此时也会触发fallback定义的函数方法




同时配置blockHandler和fallback属性

@GetMapping("/fallback/{id}")
//同时添加SentinelResource注解的fallback和blockHandler属性 exceptionsToIgnore被标注的异常将会被 原样抛出
@SentinelResource(value = "falllback", fallback = "fallbackHandler", blockHandler = "blockHandler", exceptionsToIgnore = {ArrayIndexOutOfBoundsException.class})
public String fallback(@PathVariable Long id){
    if (id < 0 || id > 3) {
        throw new NullPointerException("无对应的记录");
    }
    return "success";
}

//保证方法签名与原方法一致或加一个 Throwable 类型的参数
public String fallbackHandler(Long id, Throwable e) {
    return "出现未知的记录";
}

//处理Sentinel限流
public String blockHandler(Long id, BlockException e){
    return "BlockException限流";
}

添加流控规则:

七、Sentinel的注解@SentinelResource详细介绍_第8张图片

  • 在没有触发流控规则之前的异常交给fallback来处理

七、Sentinel的注解@SentinelResource详细介绍_第9张图片

  • 但是一旦触发流控规则就变成了blockHandler来处理

七、Sentinel的注解@SentinelResource详细介绍_第10张图片

exceptionsToIgnore属性

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

修改代码:

@GetMapping("/fallback/{id}")
//同时添加SentinelResource注解的fallback和blockHandler属性 exceptionsToIgnore被标注的异常将会被 原样抛出
@SentinelResource(value = "falllback", fallback = "fallbackHandler", blockHandler = "blockHandler", exceptionsToIgnore = {NullPointerException.class})
public String fallback(@PathVariable Long id){
    if (id < 0 || id > 3) {
        throw new NullPointerException("无对应的记录");
    }
    return "success";
}

效果:


七、Sentinel的注解@SentinelResource详细介绍_第11张图片

你可能感兴趣的:(Sentinel,sentinel,后端,微服务,spring,cloud)