序
本文主要研究一下sentinel的SentinelResourceAspect
SentinelResourceAspect
com/alibaba/csp/sentinel/annotation/aspectj/SentinelResourceAspect.java
@Aspect
public class SentinelResourceAspect {
private final Logger logger = LoggerFactory.getLogger(SentinelResourceAspect.class);
@Pointcut("@annotation(com.alibaba.csp.sentinel.annotation.SentinelResource)")
public void sentinelResourceAnnotationPointcut() {
}
@Around("sentinelResourceAnnotationPointcut()")
public Object invokeResourceWithSentinel(ProceedingJoinPoint pjp) throws Throwable {
Method originMethod = getMethod(pjp);
SentinelResource annotation = originMethod.getAnnotation(SentinelResource.class);
if (annotation == null) {
// Should not go through here.
throw new IllegalStateException("Wrong state for SentinelResource annotation");
}
String resourceName = annotation.value();
EntryType entryType = annotation.entryType();
Entry entry = null;
try {
ContextUtil.enter(resourceName);
entry = SphU.entry(resourceName, entryType);
Object result = pjp.proceed();
return result;
} catch (BlockException ex) {
return handleBlockException(pjp, annotation, ex);
} finally {
if (entry != null) {
entry.exit();
}
ContextUtil.exit();
}
}
//......
}
- 使用aspect的around拦截,拦截标注有SentinelResource的注解
- 进入方法之前调用SphU.entry(resourceName, entryType),结束之后调用entry.exit();
- 异常的时候调用handleBlockException方法
handleBlockException
private Object handleBlockException(ProceedingJoinPoint pjp, SentinelResource annotation, BlockException ex)
throws Exception {
// Execute fallback for degrading if configured.
Object[] originArgs = pjp.getArgs();
if (isDegradeFailure(ex)) {
Method method = extractFallbackMethod(pjp, annotation.fallback());
if (method != null) {
return method.invoke(pjp.getTarget(), originArgs);
}
}
// Execute block handler if configured.
Method blockHandler = extractBlockHandlerMethod(pjp, annotation.blockHandler(), annotation.blockHandlerClass());
if (blockHandler != null) {
// Construct args.
Object[] args = Arrays.copyOf(originArgs, originArgs.length + 1);
args[args.length - 1] = ex;
if (isStatic(blockHandler)) {
return blockHandler.invoke(null, args);
}
return blockHandler.invoke(pjp.getTarget(), args);
}
// If no block handler is present, then directly throw the exception.
throw ex;
}
- 这里会先判断是否是降级需要处理的异常,是的话,则调用fallback方法,否则调用block handler方法
SentinelResource
com/alibaba/csp/sentinel/annotation/SentinelResource.java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface SentinelResource {
/**
* @return name of the Sentinel resource
*/
String value();
/**
* @return the entry type (inbound or outbound), outbound by default
*/
EntryType entryType() default EntryType.OUT;
/**
* @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 "";
}
- 这里可以定义fallback方法,以及blockHandler
小结
sentinel的SentinelResourceAspect采用aspect的around拦截SentinelResource,在执行之前进行限流判断,在捕获异常的时候,会根据异常类型判断是调用fallback方法还是调用block handler方法。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。