在前面的博客中,我給你們演示了使用 @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 切面原理。