Talk about sentinel ResourceAspect of Sentinel



This article mainly studies sentinel’s SentinelResourceAspect



public class SentinelResourceAspect {

    private final Logger logger = LoggerFactory.getLogger(SentinelResourceAspect.class);

    public void 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 {
            entry = SphU.entry(resourceName, entryType);
            Object result = pjp.proceed();
            return result;
        } catch (BlockException ex) {
            return handleBlockException(pjp, annotation, ex);
        } finally {
            if (entry != null) {
  • Use aspect’s around intercept to intercept comments marked SentinelResource
  • Entry (resourcename, entrytype) is called before entering the method, and entry.exit () is called after the end.
  • Call handleBlockException Method when Exception


    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;
  • Here, we will first judge whether it is an exception that needs to be handled for demotion. If so, we will call the fallback method, otherwise we will call the block handler method.



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 "";
  • The fallback method and blockHandler can be defined here.


Sentinel’s SentinelResourceaspect uses Aspect’s around to intercept SentinelResource, and performs current limit judgment before execution. When capturing an exception, it will judge whether to call the fallback method or the block handler method according to the exception type.