@SentinelResource 注解的使用方法
官网文档:Sentinel 注解支持
对应 Spring 中的切面:SentinelResourceAspect
/**
* Aspect for methods with {@link SentinelResource} annotation.
*
* @author Eric Zhao
*/
@Aspect
public class SentinelResourceAspect extends AbstractSentinelAspectSupport {// 抽象的父类包含一些通用的方法
@Pointcut("@annotation(com.alibaba.csp.sentinel.annotation.SentinelResource)")// 切点
public void sentinelResourceAnnotationPointcut() {
}
@Around("sentinelResourceAnnotationPointcut()")
public Object invokeResourceWithSentinel(ProceedingJoinPoint pjp) throws Throwable {
Method originMethod = resolveMethod(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 = getResourceName(annotation.value(), originMethod);
EntryType entryType = annotation.entryType();
int resourceType = annotation.resourceType();
Entry entry = null;
try {// 每次请求都会创建新的 entry 对象,记录了请求开始的时间,然后会在 slot chain 上经过授权,流控,降级等一系列 check 之后,没通过 check 会抛出对应的异常
entry = SphU.entry(resourceName, resourceType, entryType, pjp.getArgs());// 最后进入 statisticsSlot 记录各项统计数据
Object result = pjp.proceed();// 如果请求被拒绝了会抛出 BlockException,直接进入 catch 分支了,也就不会访问资源了
return result;
} catch (BlockException ex) {// DegradeException、FlowException 等异常的父类
return handleBlockException(pjp, annotation, ex);// 处理请求被拒绝的情况 blockHandler,如果没有 blockHandler 则会尝试调用 fallback 方法
} catch (Throwable ex) {// 访问的资源内部抛出了异常,也就是业务异常
Class<? extends Throwable>[] exceptionsToIgnore = annotation.exceptionsToIgnore();// 需要忽略的异常
// The ignore list will be checked first.
if (exceptionsToIgnore.length > 0 && exceptionBelongsTo(ex, exceptionsToIgnore)) {
throw ex;// 该异常属于 ignore,那么直接上抛,不做处理
}
if (exceptionBelongsTo(ex, annotation.exceptionsToTrace())) {
traceException(ex);// 属于需要 trace 的异常,将该异常放入 entry 中,exit 时去处理
return handleFallback(pjp, annotation, ex);// 调用可能存在的 fallback 方法
}
// No fallback function can handle the exception, so throw it out.
throw ex;
} finally {
if (entry != null) {
entry.exit(1, pjp.getArgs());// entry 和 exit 成对使用,记录最终请求的响应时间
}
}
}
}