Sentinel源码—7.参数限流和注解的实现二

大纲

1.参数限流的原理和源码

2.@SentinelResource注解的使用和实现

2.@SentinelResource注解的使用和实现

(1)@SentinelResource注解的使用

(2)@SentinelResource注解和实现

(1)@SentinelResource注解的使用

一.引入Sentinel Spring Boot Starter依赖

复制代码
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-sentinel</artifactId>
    <version>2.2.1.RELEASE</version>
</dependency>

二.为方法添加@SentinelResource注解

下面的代码为sayHello()方法添加了@SentinelResource注解,并指定了资源名称为sayHello以及熔断降级时的回调方法fallback()。这样在请求sayHello()方法后,就可以在Sentinel Dashboard上看到此资源,然后就可以针对此资源进行一系列的规则配置了。

复制代码
@Service
public class MyService {
    @SentinelResource(value = "sayHello", fallback = "fallback")
    public String sayHello(String name) {
        return "Hello, " + name;
    }

    public String fallback(String name, Throwable throwable) {
        return "Fallback: " + name + ", reason: " + throwable.getMessage();
    }
}

(2)@SentinelResource注解和实现

利用Spring AOP拦截@SentinelResource注解,最后调用SphU.entry()方法来进行处理。

复制代码
//Aspect for methods with {@link SentinelResource} annotation.
@Aspect
public class SentinelResourceAspect extends AbstractSentinelAspectSupport {
    //SentinelResource注解
    @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注解,有了这个注解,就可以获取到注解的各种属性值了
        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对象,通过SphU.entry(resourceName)将当前方法纳入Sentinel的保护体系
        //如果当前资源的调用未触发任何Sentinel规则,则正常执行被拦截的方法,否则将执行对应的限流、熔断降级等处理逻辑
        Entry entry = null;
        try {
            entry = SphU.entry(resourceName, resourceType, entryType, pjp.getArgs());
            return pjp.proceed();
        } catch (BlockException ex) {
            //发生异常时,通过反射执行在注解中设置的降级方法
            return handleBlockException(pjp, annotation, ex);
        } 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;
            }
            if (exceptionBelongsTo(ex, annotation.exceptionsToTrace())) {
                traceException(ex);
                return handleFallback(pjp, annotation, ex);
            }
            //No fallback function can handle the exception, so throw it out.
            throw ex;
        } finally {
            if (entry != null) {
                entry.exit(1, pjp.getArgs());
            }
        }  
    }
}

//Some common functions for Sentinel annotation aspect.
public abstract class AbstractSentinelAspectSupport {
    ...
    protected Object handleBlockException(ProceedingJoinPoint pjp, SentinelResource annotation, BlockException ex) throws Throwable {
        //Execute block handler if configured.
        Method blockHandlerMethod = extractBlockHandlerMethod(pjp, annotation.blockHandler(), annotation.blockHandlerClass());
        if (blockHandlerMethod != null) {
            Object[] originArgs = pjp.getArgs();
            //Construct args.
            Object[] args = Arrays.copyOf(originArgs, originArgs.length + 1);
            args[args.length - 1] = ex;
            return invoke(pjp, blockHandlerMethod, args);
        }
        //If no block handler is present, then go to fallback.
        return handleFallback(pjp, annotation, ex);
    }

    private Object invoke(ProceedingJoinPoint pjp, Method method, Object[] args) throws Throwable {
        try {
            if (!method.isAccessible()) {
                makeAccessible(method);
            }
            if (isStatic(method)) {
                return method.invoke(null, args);
            }
            return method.invoke(pjp.getTarget(), args);
        } catch (InvocationTargetException e) {
            //throw the actual exception
            throw e.getTargetException();
        }
    }
    ...
}
相关推荐
tb_first26 分钟前
LangChain4j简单入门
java·spring boot·langchain4j
独自破碎E33 分钟前
【BISHI9】田忌赛马
android·java·开发语言
范纹杉想快点毕业39 分钟前
实战级ZYNQ中断状态机FIFO设计
java·开发语言·驱动开发·设计模式·架构·mfc
smileNicky1 小时前
布隆过滤器怎么提高误差率
java
それども1 小时前
分库分表的事务问题 - 怎么实现事务
java·数据库·mysql
Java面试题总结1 小时前
基于 Java 的 PDF 文本水印实现方案(iText7 示例)
java·python·pdf
马猴烧酒.2 小时前
【面试八股|Java集合】Java集合常考面试题详解
java·开发语言·python·面试·八股
测试工程师成长之路2 小时前
Serenity BDD 框架:Java + Selenium 全面指南(2026 最新)
java·开发语言·selenium
lang201509282 小时前
Java JSON绑定API:JSR 367详解
java·java-ee
eWidget2 小时前
随机森林原理:集成学习思想 —— Java 实现多棵决策树投票机制
java·数据库·随机森林·集成学习·金仓数据库