在前面的博客中,我给你们演示了使用 @SentinelResource 定义资源完成限流的例子,
下面就从源码解析开始,看下SentinelResource是如何实现限流的,以及@SentinelResource提供了哪些功能,支持哪些属性。spring
@SentinelResource能够说是Sentinel学习的突破口,搞懂了这个注解的应用,
基本上就搞清楚了 Sentinel 的大部分应用场景。app
Sentinel 提供了 @SentinelResource 注解用于定义资源,
并提供了 AspectJ 的扩展用于自动定义资源、处理 BlockException 等。ide
查看 Sentinel的源码,能够看到 SentinelResource 定义了value,
entryType,resourceType,blockHandler,fallback,defaultFallback等属性。函数
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface SentinelResource { /** * @return */ String value() default ""; /** * @return the entry type (inbound or outbound), outbound by default */ EntryType entryType() default EntryType.OUT; /** * @return the classification (type) of the resource * @since 1.7.0 */ int resourceType() default 0; /** * @return name of the block exception function, empty by default */ String blockHandler() default ""; /** * 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 {}; /** * @return name of the fallback function, empty by default */ String fallback() default ""; /** * The {@code defaultFallback} is used as the default universal fallback method. * It should not accept any parameters, and the return type should be compatible * @return name of the default fallback method, empty by default * @since 1.6.0 */ String defaultFallback() default ""; /** * 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 * @return the class where the fallback method is located (only single class) * @since 1.6.0 */ Class<?>[] fallbackClass() default {}; /** * @return the list of exception classes to trace, {@link Throwable} by default * @since 1.5.1 */ Class<? extends Throwable>[] exceptionsToTrace() default {Throwable.class}; /** * 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 {}; }
参考源码的注释,逐个解释下这几个属性的做用。学习
资源名称,必需项,由于须要经过resource name找到对应的规则,这个是必须配置的。code
entry 类型,可选项,
有IN和OUT两个选项,默认为 EntryType.OUT。xml
public enum EntryType { IN("IN"), OUT("OUT"); }
blockHandler 对应处理 BlockException 的函数名称,可选项。
blockHandler 函数访问范围须要是 public,返回类型须要与原方法相匹配,
参数类型须要和原方法相匹配而且最后加一个额外的参数,类型为 BlockException。对象
blockHandler 函数默认须要和原方法在同一个类中,若是但愿使用其余类的函数,
则须要指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,不然没法解析。blog
fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。
fallback 函数能够针对全部类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。资源
fallbackClass的应用和blockHandlerClass相似,fallback 函数默认须要和原方法在同一个类中。
若但愿使用其余类的函数,则能够指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,不然没法解析。
若是没有配置defaultFallback方法,默认都会走到这里来。
默认的 fallback 函数名称,可选项,一般用于通用的 fallback 逻辑。
默认 fallback 函数能够针对全部类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。
若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。
用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。
应用 @SentinelResource 注解,必须开启对应的切面,引入SentinelResourceAspect。
Sentinel支持 AspectJ 的扩展用于自动定义资源、处理 BlockException 等,
若是应用中开启了 AspectJ,那么须要在 aop.xml 文件中引入对应的 Aspect:
<aspects> <aspect name="com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect"/> </aspects>
若是应用中使用了 Spring AOP,须要在代码中添加SentinelResourceAspect的Bean,
经过配置的方式将 SentinelResourceAspect 注册为一个 Spring Bean:
@Configuration public class SentinelAspectConfiguration { @Bean public SentinelResourceAspect sentinelResourceAspect() { return new SentinelResourceAspect(); } }
这节内容学习了@SentinelResource的相关属性, 以及在项目中经过切面开启SentinelResource的方式, 不过为何使用@SentinelResource必须开启切面? 下一节就学习下 Sentinel中的 SentinelResourceAspect 切面原理。