@SentinelResource注解使用详解

前言

现在我们了解到通过Sentinel控制对Spring mvc接口层级的控制,那么在我们实际项目开发时不仅仅限于接口,可能对于某个方法的调用限流,对于某个外部资源的调用限流等都希望做到控制。
那么如何使用@SentinelResource注解灵活的定义控制资源以及如何配置控制策略。

自定义资源点

下面的例子基于您已经引入了Spring Cloud Alibaba Sentinel为基础。
第一步:在应用主类中增加注解支持的配置:

@SpringBootApplication
public class TestApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }

    // 注解支持的配置Bean
    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }

}

第二步:在需要通过Sentinel来控制流量的地方使用@SentinelResource注解,比如下面以控制Service逻辑层的某个方法为例:

@Slf4j
@Service
public class TestService {

    @SentinelResource(value = "doSomeThing")
    public void doSomeThing(String str) {
        log.info(str);
    }

}

到这里一个需要被保护的方法就定义完成了。下面我们分别说说,定义了资源点之后,我们如何实现不同的保护策略,包括:限流、降级等。

如何实现限流与熔断降级

在定义了资源点之后,我们就可以通过Dashboard来设置限流和降级策略来对资源点进行保护了。同时,也可以通过@SentinelResource来指定出现限流和降级时候的异常处理策略。下面,就来一起分别看看限流和降级都是如何实现的。

实现限流控制

第一步:在Web层调用这个被保护的方法:

@RestController
public class TestController {

    @Autowired
    private TestService testService;

    @GetMapping("/hello")
    public String hello() {
        estService.doSomeThing("hello " + new Date());
        return "didispace.com";
    }

}

第二步:启动测试应用,启动Sentinel-Dashboard。发一个请求到/hello接口上,使得Sentinel-Dashboard上可以看到如下图所示的几个控制点:
@SentinelResource注解使用详解_第1张图片现在我们可以看到/hello资源点之外,多了一个doSomeThing资源点。现在我们可以通过浏览器来请求资源。可以看到如下日志:
在这里插入图片描述

实现限流的异常处理

默认情况下,Sentinel对控制资源的限流处理是直接抛出异常。这样对用户交流不友好,我们需要处理一下异常信息

@Slf4j
@Service
public class TestService {

    // 限流与阻塞处理
    @SentinelResource(value = "doSomeThing", blockHandler = "exceptionHandler")
    public void doSomeThing(String str) {
        log.info(str);
    }

    public void exceptionHandler(String str, BlockException ex) {
        log.error("blockHandler:" + str, ex);
    }

    // 熔断与降级处理
    @SentinelResource(value = "doSomeThing2", fallback = "fallbackHandler")
    public void doSomeThing2(String str) {
        log.info(str);
        throw new RuntimeException("发生异常");
    }

    public void fallbackHandler(String str) {
        log.error("fallbackHandler:" + str);
    }

}

上面代码处理异常注意做了如下操作:

  • 通过@SentinelResource注解的blockHandler属性制定具体的处理函数
  • 实现处理函数,该函数的传参必须与资源点的传参一样,并且最后加上BlockException异常参数;同时,返回类型也必须一样。

实现熔断降级

@SentinelResource注解除了可以用来做限流控制之外,还能实现与Hystrix类似的熔断降级策略。
第一步:与限流控制一样,使用@SentinelResource注解标记资源点,比如:


    // 熔断与降级处理
    @SentinelResource(value = "doSomeThing2", fallback = "fallbackHandler")
    public void doSomeThing2(String str) {
        log.info(str);
        throw new RuntimeException("发生异常");
    }

    public void fallbackHandler(String str) {
        log.error("fallbackHandler:" + str);
    }

这里在TestService类中创建了一个新的方法,并使用@SentinelResource将该资源命名为doSomeThing2。该方法会抛出异常,以配合后续制定基于异常比例的降级策略(类似Hystrix)。Sentinel相比Hystrix更丰富,还有基于响应时间和异常数的降级策略。
第二步:在Web层调用这个被保护的方法:

@RestController
public class TestController {

    @Autowired
    private TestService testService;

    @GetMapping("/hello2")
    public String hello2() {
        testService.doSomeThing2("hello2 " + new Date());
        return "didispace.com";
    }

}

第三步:启动测试应用,启动Sentinel-Dashboard。发一个请求到/hello2接口上,使得Sentinel-Dashboard上可以看到名为doSomeThing2的资源点。然后点击”降级“按钮,为该资源设置降级规则。这里使用异常比例策略,比例设置为0.5(即:50%的异常率),时间窗口设置为2(秒)。
@SentinelResource注解使用详解_第2张图片第四步:验证熔断降级,根据上面的降级策略配置,当doSomeThing2方法的调用QPS >= 5,如果异常率超过50%,那么后续2秒内的调用将直接出发熔断降级,默认情况会直接抛出DegradeException异常,比如:

熔断的降级处理

在Sentinel中定义熔断的降级处理方法非常简单,与Hystrix非常相似。只需要使用@SentinelResource注解的fallback属性来指定具体的方法名即可。这里也需要注意传参与返回必须一致。比如:

@Slf4j
@Service
public class TestService {

    // 熔断与降级处理
    @SentinelResource(value = "doSomeThing2", fallback = "fallbackHandler")
    public void doSomeThing2(String str) {
        log.info(str);
        throw new RuntimeException("发生异常");
    }

    public void fallbackHandler(String str) {
        log.error("fallbackHandler:" + str);
    }
}

oSomeThing2资源的熔断降级策略(使用异常百分比),然后频繁的请求/hello2接口。在QPS>=5之后,由于这个接口一直在抛出异常,所以一定会满足熔断降级条件,这时候就会执行fallbackHandler方法,不断的打印如下日志:
在这里插入图片描述

更多注解属性说明

@SentinelResource注解最主要的两个用法:限流控制和熔断降级的具体使用案例介绍完了。另外,该注解还有一些其他更精细化的配置,比如忽略某些异常的配置、默认降级函数等等,具体可见如下说明:

  • value:资源名称,必需项(不能为空)
  • entryTypeentry类型,可选项(默认为 EntryType.OUT)
  • fallbackfallback函数名称,可选项,用于在抛出异常的时候提供 fallback处理逻辑。fallback函数可以针对所有类型的异常(除了exceptionsToIgnore里面排除掉的异常类型)进行处理。fallback函数签名和位置要求: 返回值类型必须与原函数返回值类型一致;方法参数列表需要和原函数一致,或者可以额外多一个 Throwable类型的参数用于接收对应的异常。
  • fallback函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass为对应的类的 Class 对象,注意对应的函数必需为 static函数,否则无法解析。 defaultFallback(since 1.6.0):默认的 fallback函数名称,可选项,通常用于通用的 fallback逻辑(即可以用于很多服务或方法)。默认 fallback函数可以针对所有类型的异常(除了exceptionsToIgnore里面排除掉的异常类型)进行处理。若同时配置了 fallbackdefaultFallback,则只有 fallback会生效。defaultFallback函数签名要求:返回值类型必须与原函数返回值类型一致;
  • 方法参数列表需要为空,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
  • defaultFallback函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
    exceptionsToIgnore(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。

参考文档

系列教材

你可能感兴趣的:(spring)