@SentinelResource注解详解

SpringCloudAlibaba-Sentinel 这篇文档中,我们已经介绍了大致的Sentinel相关知识。
但是 @SentinelResource 这个注解在那篇文档中并没有过多提及其详细内容,也就是简单提了一嘴。
那篇文档的 注解介绍位置 :https://www.yuque.com/shmily-kbnvv/xxbj/ci2gs5#9lIy9 //todo 待修改成csdn地址

我们在此进行一个详细介绍,首先此注解类似于Hystrix中的 @HystrixCommand 注解,指示Sentinel资源的定义,是定义在方法上的注解,定义控制资源以及如何配置控制策略。
比如控制某个方法被限流了、被熔断了、报错了之后应该调用哪个方法。

@SentinelResource注解详解_第1张图片
通过查看源码,我们可以看到该注解一共有这么多个属性:
@SentinelResource注解详解_第2张图片
然后我们对它一一进行解释。

  • value: Sentinel资源的名称,我们不仅可以通过url进行限流,也可以把此值作为资源名配置,一样可以限流。
  • entryType: 条目类型(入站或出站),默认为出站(EntryType.OUT)
  • resourceType: 资源的分类(类型)
  • blockHandler: 块异常函数的名称,默认为空
  • blockHandlerClass: 指定块处理方法所在的类
    • 默认情况下, blockHandler与原始方法位于同一类中。 但是,如果某些方法共享相同的签名并打算设置相同的块处理程序,则用户可以设置存在块处理程序的类。 请注意,块处理程序方法必须是静态的。
  • fallback: 后备函数的名称,默认为空
  • defaultFallback: 默认后备方法的名称,默认为空
    • defaultFallback用作默认的通用后备方法。 它不应接受任何参数,并且返回类型应与原始方法兼容
  • fallbackClass: fallback方法所在的类(仅单个类)
    • 默认情况下, fallback与原始方法位于同一类中。 但是,如果某些方法共享相同的签名并打算设置相同的后备,则用户可以设置存在后备功能的类。 请注意,共享的后备方法必须是静态的。
  • exceptionsToTrace: 异常类的列表追查,默认 Throwable
  • exceptionsToIgnore: 要忽略的异常类列表,默认情况下为空

然后我们对其进行一一的详细介绍:

value

    /**
     * @return name of the Sentinel resource
     */
    String value() default "";

我们可以通过 @SentinelResource 注解的value值定义该方法对应的资源名。
举个例子:

        //这两种写法是一样的,但是当配置多个参数的时候,就必须带上value这个属性名了。
        @SentinelResource("helloSentinelResource")
        // @SentinelResource(value = "helloSentinelResource")
        public String helloSentinelResource(){
            return "helloSentinelResource";
        }

那么使用这个注解并配置此属性有什么作用呢?
这个注解的value值指定了我们配置的此api资源的名称,在我们的限流、熔断的配置中,均可以使用(限流、熔断中也可以使用@RequestMapping配置的url)。
我们下面举个限流的例子:
定义了一个接口:

        @RequestMapping("/helloRequestMapping")
        @SentinelResource("helloSentinelResource")
        public String sentinelResource(){
            return "sentinelResource";
        }

在Sentinel控制台进行配置:
首先使用 @RequestMapping 的值进行配置并保存。
连续访问此接口两次(一秒内),会发现:接口被限流了。
@SentinelResource注解详解_第3张图片
然后再使用 @SentinelResource 的值进行配置并保存(记得删除刚刚配置的内容)。
连续访问此接口两次(一秒内),会发现:接口被限流了(虽然展示内容不一样,但是都被限流了是实打实的)。
@SentinelResource注解详解_第4张图片

entryType

资源调用的流量类型,入口流量还是出口流量。

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

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

        @RequestMapping("/out")
        @SentinelResource(value = "entryTypeOut",entryType = EntryType.OUT)
        public String entryTypeOut() throws InterruptedException {
            return "sentinelResource";
        }

        @RequestMapping("/in")
        @SentinelResource(value = "entryTypeIn",entryType = EntryType.IN)
        public String entryTypeIn() throws InterruptedException {
            return "sentinelResource";
        }

@SentinelResource注解详解_第5张图片
然后对每个接口都进行1秒钟2次的访问,我们可以发现,entryType = EntryType.OUT 的接口没有被限流,entryType = EntryType.IN 的接口被限流了。
image.png

resourceType

资源的分类(类型)
用于标识资源的分类,0-通用、1-WEB、2-RPC、3-GATEWAY、4-SQL,在 ResourceTypeConstants 类里有定义。

这个数字对应啥我是通过官方文档、源码、注解等都都没找到,问别人才知道的。如果谁看到了在哪有相关信息能指引到这个类,告诉我一声。

    /**
     * @return the classification (type) of the resource
     * @since 1.7.0
     */
    int resourceType() default 0;

在Sentinel的实时监控中有个字段是资源分类,可以将资源分类作为条件。
参考:https://github.com/alibaba/Sentinel/wiki/实时监控#资源的秒级日志
@SentinelResource注解详解_第6张图片

blockHandler

块异常函数的名称,默认为空。
blockHandler 对应处理 BlockException 的方法名称,可选项。
正常来说我们如果达到了限流阈值、被熔断了报错之后,是会将500错误页面进行返回的。如果我们配置了blockHandler这个属性,他就会执行名称为这个属性的值的方法。

    /**
     * @return name of the block exception function, empty by default
     */
    String blockHandler() default "";

配置作为这个属性值的方法有几个要求:

  • 方法名:随便定义
  • 作用域:public
  • 参数:要和原方法一致的基础上,在最后面加上一个类型为BlockException的参数。
  • 返回类型:要和原方法一致。
  • 静态?:若使用了blockHandlerClass指定其他类中的方法,那么这个方法必须是static的,否则无法解析。

测试:
编写两个方法,一个我们访问的方法,一个访问出错了(被限流、熔断)之后访问的方法,并在控制台进行限流配置。

        @RequestMapping("/blockHandler")
        @SentinelResource(value = "blockHandler", blockHandler = "blockHandlerErr")
        public String blockHandler() {
            return "blockHandler O(∩_∩)O";
        }

        public String blockHandlerErr(BlockException be) {
            return "blockHandler ┭┮﹏┭┮";
        }

@SentinelResource注解详解_第7张图片
由于配置的限流阈值是1,所以当一秒钟访问一次的时候显示 blockHandler 方法的返回内容,访问两次以上的时候显示 blockHandlerErr 方法的返回内容。
image.png

blockHandlerClass

指定块处理方法所在的类
fallback 方法默认需要和原方法在同一个类中,如果指定了blockHandlerClass属性的值,则使用指定类中的方法。
如果是其他类中的方法,该方法必须是静态(static)的。

    /**
     * The {@code blockHandler} is located in the same class with the original method by default.
     * However, if some methods share the same signature and intend to set the same block handler,
     * then users can set the class where the block handler exists. Note that the block handler method
     * must be static.
     *
     * @return the class where the block handler exists, should not provide more than one classes
     */
    Class<?>[] blockHandlerClass() default {};

测试:
使用 blockHandlerClass 参数指定需要使用哪个类中的方法,注意指定类中的方法一定要是静态的,无论是其他的类还是本类(当然,本类中的方法不需要用这个参数,直接就默认本类,而且不需要静态,如果指定了本类的话还需要将指定方法改成静态的,多此一举,没事找事呢这是)。
然后进行限流控制,设置阈值为1,当1秒钟访问一次的时候正常,访问两次的时候就会调用指定类中的方法。
@SentinelResource注解详解_第8张图片
@SentinelResource注解详解_第9张图片

fallback

后备函数的名称,默认为空,可选项。
用于在抛出异常的时候提供 fallback 处理逻辑。 fallback 方法可以针对所有类型的异常(除了 exceptionsToIgnore 参数里面排除掉的异常类型)进行处理。
blockHandler使用方法一样,只不过是处理的异常不一样。
如果配置了blockHandler,限流、熔断的时候会执行blockHandler指定的方法,其他的异常执行 fallback 指定的方法。如果没配置,也执行fallback中配置的方法。

    /**
     * @return name of the fallback function, empty by default
     */
    String fallback() default "";

测试:

  1. 同时 fallbackblockHandler 都配置

如果配置了blockHandler,限流、熔断的时候会执行blockHandler指定的方法,其他的异常执行 fallback 指定的方法。

    public String blockHandlerErr(BlockException be) {
        return "blockHandler ┭┮﹏┭┮";
    }

    @RequestMapping("/fallback")
    @SentinelResource(value = "fallback", fallback = "fallbackErr", blockHandler = "blockHandlerErr")
    public String fallback() {
        int i = 1 / 0;
        return "fallback O(∩_∩)O";
    }

    public String fallbackErr() {
        return "fallback ┭┮﹏┭┮";
    }

@SentinelResource注解详解_第10张图片

  1. 只配置 fallback

如果没配置blockHandler,限流、熔断的时候也执行fallback中配置的方法。

    public String blockHandlerErr(BlockException be) {
        return "blockHandler ┭┮﹏┭┮";
    }

    @RequestMapping("/fallback")
    @SentinelResource(value = "fallback", fallback = "fallbackErr")
    public String fallback() {
        int i = 1 / 0;
        return "fallback O(∩_∩)O";
    }

    public String fallbackErr() {
        return "fallback ┭┮﹏┭┮";
    }

@SentinelResource注解详解_第11张图片

defaultFallback

如果没有配置fallback的值,默认都会走到这里来。 默认的 fallback 方法名称,可选项,通常用于通用的 fallback 逻辑。 默认 fallback 方法可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。 若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。

测试:

  1. 同时配置了 fallback 参数和 defaultFallback 参数:
    @RequestMapping("/fallback")
    @SentinelResource(value = "fallback", fallback = "fallbackErr",defaultFallback = "defaultFallbackErr")
    public String fallback() {
        int i = 1 / 0;
        return "fallback O(∩_∩)O";
    }

    public String fallbackErr() {
        return "fallback ┭┮﹏┭┮";
    }
    public String defaultFallbackErr() {
        return "defaultFallback ┭┮﹏┭┮";
    }

@SentinelResource注解详解_第12张图片

  1. 只配置了defaultFallback 参数:
    @RequestMapping("/fallback")
    @SentinelResource(value = "fallback", defaultFallback = "defaultFallbackErr")
    public String fallback() {
        int i = 1 / 0;
        return "fallback O(∩_∩)O";
    }

    public String fallbackErr() {
        return "fallback ┭┮﹏┭┮";
    }

    public String defaultFallbackErr() {
        return "defaultFallback ┭┮﹏┭┮";
    }

@SentinelResource注解详解_第13张图片

fallbackClass

指定块处理方法所在的类
fallback 方法默认需要和原方法在同一个类中,如果指定了blockHandlerClass属性的值,则使用指定类中的方法。
如果是其他类中的方法,该方法必须是静态(static)的。

    /**
     * The {@code fallback} is located in the same class with the original method by default.
     * However, if some methods share the same signature and intend to set the same fallback,
     * then users can set the class where the fallback function exists. Note that the shared fallback method
     * must be static.
     *
     * @return the class where the fallback method is located (only single class)
     * @since 1.6.0
     */
    Class<?>[] fallbackClass() default {};

实际使用和 blockHandlerClass 几乎一样,这里就不展示测试过程了。

exceptionsToTrace

用于指定哪些异常被统计,与 exceptionsToIgnore 相反。可选。默认Throwable。
一般与 fallback 搭配使用。

    /**
     * @return the list of exception classes to trace, {@link Throwable} by default
     * @since 1.5.1
     */
    Class<? extends Throwable>[] exceptionsToTrace() default {Throwable.class};

测试:
编写两个方法,一个接口方法、一个fallback指定方法。
接口方法中,当传入参数 num=1 的时候,抛出 ArrayIndexOutOfBoundsException 异常,当传入参数 num=2 时,抛出 NumberFormatException 异常。
通过 exceptionsToTracefallback控制,只统计 ArrayIndexOutOfBoundsException 异常,当出现 ArrayIndexOutOfBoundsException 异常的时候,调用 exceptionsToTraceFallbackErr 方法(其他异常则不进行处理)。

    @RequestMapping("/exceptionsToTrace")
    @SentinelResource(value = "exceptionsToTrace",
            exceptionsToTrace = ArrayIndexOutOfBoundsException.class,
            fallback = "exceptionsToTraceFallbackErr")
    public String exceptionsToTrace(int num) {
        if (num == 1) {
            int[] ints = {1, 2, 3};
            System.out.println(ints[10]);
        } else {
            int i = Integer.valueOf("s");
        }
        return "exceptionsToTrace O(∩_∩)O";
    }

    public String exceptionsToTraceFallbackErr(int num) {
        return "exceptionsToTraceFallbackErr ┭┮﹏┭┮";
    }

@SentinelResource注解详解_第14张图片

exceptionsToIgnore

用于指定哪些异常被忽略,与 exceptionsToTrace 相反。可选。默认空。
一般与 fallback 搭配使用。

    /**
     * Indicates the exceptions to be ignored. Note that {@code exceptionsToTrace} should
     * not appear with {@code exceptionsToIgnore} at the same time, or {@code exceptionsToIgnore}
     * will be of higher precedence.
     *
     * @return the list of exception classes to ignore, empty by default
     * @since 1.6.0
     */
    Class<? extends Throwable>[] exceptionsToIgnore() default {};

测试:
编写两个方法,一个接口方法、一个fallback指定方法。
接口方法中,当传入参数 num=1 的时候,抛出 ArrayIndexOutOfBoundsException 异常,当传入参数 num=2 时,抛出 NumberFormatException 异常。
通过 exceptionsToIgnorefallback控制,不统计 ArrayIndexOutOfBoundsException 异常,当出现 ArrayIndexOutOfBoundsException 异常的时候,调用 exceptionsToIgnoreFallbackErr 方法(其他异常则不进行处理)。

    @RequestMapping("/exceptionsToIgnore")
    @SentinelResource(value = "exceptionsToIgnore",
            exceptionsToTrace = ArrayIndexOutOfBoundsException.class,
            fallback = "exceptionsToIgnoreFallbackErr")
    public String exceptionsToIgnore(int num) {
        if (num == 1) {
            int[] ints = {1, 2, 3};
            System.out.println(ints[10]);
        } else {
            int i = Integer.valueOf("s");
        }
        return "exceptionsToIgnore O(∩_∩)O";
    }

    public String exceptionsToIgnoreFallbackErr(int num) {
        return "exceptionsToIgnoreFallbackErr ┭┮﹏┭┮";
    }

@SentinelResource注解详解_第15张图片

相关内容

额外提一个类 SentinelResourceAspect ,也就是这个注解怎么实现的。
如果想看@SentinelResource是怎么生效的,就看下这个类的源码就懂啦。
完整路径:com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect.java


相关代码下载地址:https://download.csdn.net/download/wangguohui0726/16698689










你可能感兴趣的:(Java,#,SpringCloud,java,spring,cloud,spring,cloud,alibaba)